#include <iostream>
using namespace std;
class Rectangle;
int main () {
Rectangle rect (3,4);
Rectangle rectb (5,6);
cout << "rect area: " << rect.area() << endl;
cout << "rectb area: " << rectb.area() << endl;
return 0;
}
class Rectangle {
int width, height;
public:
Rectangle (int,int);
int area () {return (width*height);}
};
Rectangle::Rectangle (int a, int b) {
width = a;
height = b;
}
我知道有很多这样的帖子,但是他们似乎都没有修复我的错误Variable has incomplete type (class_name_here)
。
我想要做的就是,在主块之后创建类,并通过在主块之前创建“原型”来完全使用它。我想:嗯,这很简单,但是无法解决它。
答案 0 :(得分:5)
类型的前向声明会创建一个所谓的不完整类型 - 一种已知存在的类型,但其特征尚不清楚。
您无法声明不完整类型的变量。这是因为编译器需要知道为Rectangle
对象分配多少空间以及该类型存在哪些构造函数。请注意,由于编译器尚未看到该方法的声明,因此您无法在对象上调用area()
。
指针或引用的简单赋值,或者将它们传递给接受指针/引用的其他函数,直到类型完成。
class Rectangle;
Rectangle & get_rectangle();
int main(void) {
// OK, this is a reference.
Rectangle & r = get_rectangle();
// OK, this is a pointer.
Rectangle * rp = &r;
// Not OK; the compiler doesn't know (a) how much space to allocate on the stack,
// nor (b) if the type has a default constructor.
Rectangle rect;
// Not OK; the compiler has not seen a declaration of Rectangle so it doesn't know
// whether the area() method exists, nor its signature.
r.area();
rp->area();
return EXIT_SUCCESS;
}
通常,当类型之间存在某种循环依赖关系时,使用类型的前向声明,例如某些子节点类型需要引用其父节点,但父类型包含子节点。
class Parent;
class Child {
private:
Parent & parent;
};
class Parent {
private:
std::vector<Child> children;
};
opaque指针idiom 或 pimpl pattern 也使用了这种技术,您可以将类中的所有数据成员存储在另一个类型未公开的对象中消耗它的代码。这允许您在不破坏代码的二进制接口的情况下更改数据成员。 (例如,添加或删除或更改数据成员通常会导致类的对象的大小和/或布局发生变化。这种方法会导致大小保持不变;您只需存储指向数据的指针,并且< em> data 类可以在消费者不必了解或关心的情况下更改布局。)
class Something {
private:
class Data;
std::unique_ptr<Data> data;
};
使用您的库的代码不知道Something::Data
是什么,但它不需要关心。然后在Something
的实现文件中定义此类。
在您的情况下,没有理由使用前瞻性声明。只需将前向声明替换为实际的类定义。