为什么我们不能用抽象类创建容器?
Why we couldn't create container with abstract class?
我试图创建抽象类的向量,但它给了我编译错误。 代码是:
class Base
{
public :
int _b;
virtual void virtualFunc() = 0;
};
int _tmain(int argc, _TCHAR* argv[])
{
std::vector<Base> vec;
}
我得到的编译错误是:
error C2259: 'B' : cannot instantiate abstract class due to following members:
'void B::virtualFunc(void)' : is abstract
1)我不明白为什么我会出错,是因为矢量会尝试调用构造函数吗?是按价值传递的东西吗? 2)模板函数的行为是否相同?
1)我不明白为什么我会出错,因为矢量会尝试 调用构造函数?
是的 - 在内部,向量需要分配一个对象数组来保存您的数据,即它将尝试执行以下操作:
this->dataItems = new Base[10];
。但它不能这样做,因为 Base 是一个抽象类,因此可能不会直接实例化(在数组中或其他任何地方)。 因此错误。
是按价值传递的东西吗?
不是直接的,但是如果您的目标是获得作为 Base 的各种子类的对象向量,那么您可能希望使用:
std::vector< std::shared_ptr<Base> > vec;
。相反。 然后你可以做,例如:
vec.push_back(new Derived1()); // where Derived1 is a subclass of Base
vec.push_back(new Derived2()); // where Derived2 is another subclass of Base
vec[0]->virtualFunc(); // calls Derived1::virtualFunc()
vec[1]->virtualFunc(); // calls Derived2::virtualFunc()
这将起作用,因为向量的内部数组只是一个智能指针数组(它们是非抽象的并且都是相同类型)。
你不能直接实例化抽象类,因此抽象类的向量不能工作。
但是,如果您坚持,则可以使用指针来执行此操作。
std::vector<std::unique_ptr<Base>> vec;
当unique_ptr超出范围时,它将自动为您删除内存。
确保您使用的是unique_ptr
而不是原始指针,那么您就不必担心内存释放。
我无法用您的代码重现您的错误。
以下编译:
class Base
{
public :
int _b;
virtual void virtualFunc() = 0;
};
int main(int , char**)
{
std::vector<Base> vec;
return(0);
}
我的编译器给出以下警告:
R02: dumy506.cc
rm -f dumy506
g++-5 -m64 -O3 -ggdb -std=c++14 -Wall -Wextra -Wshadow -Wnon-virtual-dtor -pedantic -Wcast-align -Wcast-qual -Wconversion -Wpointer-arith -Wunused -Woverloaded-virtual -O0 dumy506.cc -o dumy506 -L../../bag -lbag_i686 -lposix_i686 -lrt -pthread
dumy506.cc:15:11: warning: ‘class Base’ has virtual functions and accessible non-virtual destructor [-Wnon-virtual-dtor]
class Base
我可以通过添加虚拟 dtor 来清除此警告
class Base
{
public :
virtual ~Base() = default;
int _b;
virtual void virtualFunc() = 0;
};
int main(int , char**)
{
std::vector<Base> vec;
return(0);
}
根据"http://en.cppreference.com/w/cpp/container/vector/vector","默认构造函数。构造一个空容器。
这表示您的代码不应尝试创建任何元素。
"纯方法"编译错误仅在我尝试实例化要安装到 vec 中的元素时发生。
int main(int , char**)
{
std::vector<Base> vec;
Base b; // <<< pure method error detected here
vec.push_back(b);
return(0);
}
dumy506.cc:31:12: error: cannot declare variable ‘b’ to be of abstract type ‘Base’
Base b;
^
dumy506.cc:15:11: note: because the following virtual functions are pure within ‘Base’:
class Base
^
dumy506.cc:22:21: note: virtual void Base::virtualFunc()
virtual void virtualFunc() = 0;
2017 年 7 月 22 日更新
今天,在我的系统上,vec.reserve() 触发了一个内存分配,由于纯函数而失败。
也许OP的实现(以及其他2个答案?)试图在ctor期间分配一些最小数量的元素,与 cppreference.com 相反。
也许 cppreference.com 错了,或者需求正在"移动"。
结束更新
1)我不明白为什么我会去[原文如此]错误是因为矢量会尝试 调用构造函数?
不。 可以创建一个空向量。没有实例化 B。
是按价值传递的东西吗?
我认为不是。
2)模板函数的行为是否相同?
您尚未描述已发布代码的行为。
我的系统: Ubuntu 15.10, 64 位
编译器:
~$ g++-5 --版本 g++-5 (Ubuntu 5.2.1-23ubuntu1~15.10) 5.2.1 20151028
>C++不允许创建抽象类的一个实例。因此,如果你不能制作一个对象,你将如何制作一个对象的容器?
这样想吧。动物是一个抽象的概念。狗是一种动物,因此是动物的一个子类。Fido是Dog类型的特定对象。
如果不指定对象是狗、猫、大象还是其他动物,则无法创建 Animal 类型的对象。所以你不能建立一个由"动物"组成的动物园,但你可以有一个动物园,里面有一头特定的大象,一只粒子老虎,一只特定的大猩猩,等等。
您可能想要的是指向 Base 的指针容器。
std::vector< Base * > vec;
或者更好的是,一个指向 Base 的智能指针容器。
typedef std::shared_ptr< Base > BasePtr;
std::vector< BasePtr > vec;
T
的所有容器中最基本的要求是T
是一个值类型,你可以创建它的实例。
根据定义,声明不能创建抽象类的任何实例。
根据定义,模板是元函数和元类:它们通过填充给定的模板参数来实例化。它们是创建函数和类的工具,但它们不是函数和类。当使用违反规范的模板参数时,将生成不正确的函数或类,并且错误消息将显示一堆实例化,有点像可以检查调用abort()
以查看函数调用堆栈的进程的事后转储。
错误消息的确切性质取决于容器的实现详细信息。这就是C++模板非常丑陋的本质。它本质上是一种高级宏语言。
- 无法创建抽象类的实例
- C ++如何在原始抽象类中创建一个函数,该函数接受派生类的输入
- 如何创建shared_ptr抽象类的容器
- 从抽象类继承以创建另一个抽象类时,我应该重新声明所有虚函数吗?
- 为什么我们不能用抽象类创建容器?
- 使用抽象类的类和实现此抽象类的创建对象
- 从抽象类创建链
- 如何在代码中创建抽象类,让蓝图扩展它,并将该蓝图返回给代码进行实例化?
- 如何创建抽象数据类型的模板类?
- 如何在 C++ 中创建抽象类的对象或数据结构?
- 创建抽象类 C++ 的对象
- 如何在派生实例化之前创建抽象类
- 如何创建抽象类的内联实现
- 无法在函数 main() 中创建抽象类的指针
- 在c++ /QT中创建抽象类对象的QList
- 如何创建抽象类成员
- 如何在c++中创建抽象类的数组
- 错误LNK2001:未解析的外部符号-当创建抽象类c++
- 如何创建抽象类的无名派生类的对象
- 正在创建抽象类的克隆