LINUX.ORG.RU

Зачем нужен forward declaration в C++?

 ,


0

3

Не холивара ради, сравнение кода Swift и C++:

class Object {

	let inventory = Inventory()

}

class Inventory {

	var items = [Object]()

}

class Human: Object {}

class Sandals: Object {}

class Socks: Object {}

let human = Human()
human.inventory.items.append(Socks())
human.inventory.items.append(Sandals())

print("Items count: \(human.inventory.items.count)")

Собираем, запускаем:

swiftc includeEachOther.swift -o includeTest && ./includeTest 
Items count: 2

C++:

#include <vector>
#include <iostream>

using namespace std;

class Object {

public:

	Inventory *inventory;

};

class Inventory {

public:

	vector<Object *> items;

};

class Human: public Object {};

class Sandals: public Object {};

class Socks: public Object {};

int main() {

	auto human = new Human();

	human->inventory = new Inventory();
	
	human->inventory->items.push_back(new Sandals());
	human->inventory->items.push_back(new Socks());	

	cout << "Items count: " << human->inventory->items.size() << endl;

	return 0;

};

Собираем, запускаем:

 g++ -std=c++11 includeEachOther.cpp -o includeTest && ./includeTest

includeEachOther.cpp:10:2: error: unknown type name 'Inventory'
        Inventory *inventory;
        ^

Если добавить forward declaration - class Inventory в .cpp, то все заработает. Я не понимаю почему в C++ нужно это в 2017 году, кто-нибудь может объяснить?

Ответ на: комментарий от hateyoufeel

Я намекал на атомарность, которая необходима для подсчёта ссылок.

Во-первых, ты сам заметил, что это необходимо. Во-вторых, оверхед имеет место только в случае изменения счётчика ссылок, что (при разумном использовании) бывает редко — тогда, когда без этого не обойтись (разделяется владение объектом, на который указывает указатель).

Softwayer ★★
()
Ответ на: комментарий от RazrFalcon

В джаве неплохие лямбды, например, или в хаскеле каком-нибудь.

Однако в крестах есть необходимость явно указывать, по значению кэпчурить контекст или по ссылке, и сравнивать их с языками, в которых ссылочные типы и сборка мусора, в этом контексте некорректно. В расте, насколько я знаю, есть только два варианта для всего контекста целиком: borrow и move. Едва ли часто нужно кэпчурить разные переменные по-разному, но, так или иначе, плюсовый подход обладает в этом смысле большей гибкостью.

Softwayer ★★
()
Ответ на: комментарий от Softwayer

В джаве неплохие лямбды

И чем они лучше? Синтаксис фактически тот же.

кэпчурить разные переменные по-разному

В расте тоже можно:

fn main() {
    let f = |x: i32, y: &mut Vec<i32>| {
        y.push(x);
    };
    
    let mut v = vec![1, 2, 3];
    f(4, &mut v);
    println!("{:?}", v);
}

RazrFalcon ★★★★★
()
Последнее исправление: RazrFalcon (всего исправлений: 1)
Ответ на: комментарий от RazrFalcon

Синтаксис фактически тот же

Субъективщина, конечно, но по мне x -> x выглядит существенно приятнее, чем |x| x.

В расте тоже можно.

В расте нет такого понятия, как кэпчуринг по значению (то есть с копированием), поэтому там с этим проще, да.

А твой пример ничего не кэпчурит, в него всё явно передаётся через аргументы.

Softwayer ★★
()
Последнее исправление: Softwayer (всего исправлений: 1)
Ответ на: комментарий от Softwayer

Разве не (x) -> x? И да, это не преимущество - это вкусовщина.

А твой пример ничего не кэпчурит, в него всё явно передаётся через аргументы.

Понял о чём речь, туплю уже. Да, аналога перечислений внутри [], как в C++ - нет, но и не совсем понятно где это может пригодится в расте.

RazrFalcon ★★★★★
()
Ответ на: комментарий от Macil

Могу в ответ сказать только то, что с любыми coding guidelines говнокодер родит говнокод. Призвание у него такое. Так что разруха - она в головах, а не в отсутствии запретов «сюдой не ходи - тудой ходи».

dzidzitop ★★
()
Ответ на: комментарий от anonymous

«гото не по делу» - это, например, goto для выхода из нескольких вложенных циклов, когда можно обойтись флагами и понатыкаными везде проверками «стоит ли продолжать»?

dzidzitop ★★
()
Последнее исправление: dzidzitop (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.