Abstract object cannot declare
我对抽象/虚拟类有问题,这里是对问题的复制:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | #include <iostream> class A { protected: virtual std::string getDateTime() = 0; virtual void Write(std::string data, bool addDate) = 0; virtual bool CheckFile() = 0; virtual bool OpenFile(std::string path) = 0; virtual void CloseFile() = 0; }; class B : public A { public: virtual std::string ToString() { return""; }; virtual void Write(std::string data) { }; }; class C : public A { protected: std::string getDateTime() { return"TODAY"; }; void Write(std::string data, bool addDate) { std::cout <<"BasicClassA Write" << std::endl; }; bool CheckFile() { std::cout <<"BasicClassA CheckFile" << std::endl; return true; }; bool OpenFile(std::string path) { std::cout <<"BasicClassA OpenFile" << std::endl; return true; }; void CloseFile() { std::cout <<"BasicClassA CloseFile" << std::endl; }; }; class D : public B, public C { public: BasicClassB(); virtual ~BasicClassB(); std::string ToString() { return"BasicClassB tostring"; }; void Write(std::string data) { std::cout <<"BasicClassB Write" << std::endl; }; }; int main(int ac, char *av[]) { BasicClassB b; std::cout << b.ToString() << std::endl; b.Write(""); return 0; } |
这有一个编译错误:
../src/main.cpp:在函数"int main(int,char**)"中:../src/main.cpp:82:错误:无法将变量"b"声明为抽象类型"basicclassb"../SRC/main.cpp:64:注意:因为以下虚拟函数在"basicClassB"中是纯的:./SRC/main .CPP:13:注释:虚拟STD::字符串BaseCasa::GETDATITEME()./SRC/main .CPP:14:注释:虚拟空隙BaseCasa::写(STD::字符串,BOOL)../src/main.cpp:15:注意:虚拟bool baseclassa::checkfile()./SRC/main .CPP:16:注释:虚拟BooBaseCasa::OpenFILE(STD::字符串)../src/main.cpp:17:注意:虚拟void baseclassa::closefile()
也许我这里遗漏了一点,但是baseclassa(basicclassa)的实现应该包含这些函数,而且由于basicclassb也是basicclassa的子类,所以它也应该包含这些函数?
我错过了什么?我该怎么做才能编译这个程序?
[编辑]
我需要的似乎是虚拟继承,但是,在我的案例中,我似乎没有找到正确的方法来实现这一点…
目标是要有几个"基本"类,类似接口,强制子类实现函数,但是这些类的任何子类都应该继承覆盖函数(就像虚拟继承一样)。
但是,使用任意类:公共虚拟任意其他不可行,总是给出相同的编译错误(上面的那个)。也许我需要改变的不仅仅是继承中的虚拟?
默认情况下,C++中没有这样的工作方式——你想要一个菱形继承模式,但是在C++中你得到了独立的根:所以BasicClassA和BaseClassB每个都有自己的BaseCasa(VTABLE和实例变量)。
您可能想要使用虚拟继承。
要更清楚地了解非虚拟继承:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | #include <iostream> class A { public: A(int x) {m_a = x;} virtual ~A() {} int m_a; virtual int getA() {return m_a;} }; class B : public A { public: B() : A(1) {} }; class C : public A { public: C() : A(2) {} }; class D : public B, public C { }; void useB(B* b) { std::cout <<"useB:" << b->getA() << std::endl; } void useC(C* c) { std::cout <<"useC:" << c->getA() << std::endl; } int main() { D* d = new D(); useB(d); useC(d); return 0; } |
。
这将产生输出:
1 2 | useB:1 useC:2 |
这个例子展示了虚拟继承,以及您想要的混合行为。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | #include <iostream> class A { public: A(int x) {m_a = x;} virtual ~A() {} int m_a; virtual int getA() {return m_a;} virtual int virt() = 0; }; class B : virtual public A { public: B() : A(1) {} }; class C : virtual public A { public: C() : A(2) {} virtual int virt() {return 42;} }; class D : public B, public C { public: D() : A(3) {} }; void useB(B* b) { std::cout <<"useB:" << b->getA() << std::endl; } void useC(C* c) { std::cout <<"useC:" << c->getA() << std::endl; std::cout <<"useC-virt:" << c->virt() << std::endl; } int main() { D* d = new D(); useB(d); useC(d); return 0; } |
。
输出:
1 2 3 | useB:3 useC:3 useC-virt:42 |
。
注意:C和B的构造函数在设置m_时没有发言权,m_a是d()构造函数初始化列表的控制器。
编辑:将虚拟应用于代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | #include <iostream> class A { protected: virtual std::string getDateTime() = 0; virtual void Write(std::string data, bool addDate) = 0; virtual bool CheckFile() = 0; virtual bool OpenFile(std::string path) = 0; virtual void CloseFile() = 0; }; class B : virtual public A { public: virtual std::string ToString() { return""; }; virtual void Write(std::string data) { }; }; class C : virtual public A { protected: std::string getDateTime() { return"TODAY"; }; void Write(std::string data, bool addDate) { std::cout <<"C Write" << std::endl; }; bool CheckFile() { std::cout <<"C CheckFile" << std::endl; return true; }; bool OpenFile(std::string path) { std::cout <<"C OpenFile" << std::endl; return true; }; void CloseFile() { std::cout <<"C CloseFile" << std::endl; }; }; class D : public B, public C { public: std::string ToString() { return"D tostring"; }; void Write(std::string data) { std::cout <<"D Write" << std::endl; }; }; int main(int ac, char *av[]) { D b; std::cout << b.ToString() << std::endl; b.Write(""); return 0; } |
1 2 3 4 5 | virtual std::string getDateTime() = 0; virtual void Write(std::string data, bool addDate) = 0; virtual bool CheckFile() = 0; virtual bool OpenFile(std::string path) = 0; virtual void CloseFile() = 0; |
纯粹是虚拟的。
错误消息非常清楚:为了能够实例化
另外,请注意您在
1 | virtual void Write(std::string data) { }; |
号
与
1 | virtual void Write(std::string data, bool addDate) = 0; |
因此,为了使
BaseClassA有5个纯虚拟函数。具有一个纯虚函数的类是一个"抽象类"。纯虚拟函数(简而言之)的目的是禁止创建抽象类的对象。
为了实例化baseclassb,它需要定义您在baseclassa中声明为纯虚拟的所有5个函数。(在没有这些定义的情况下,baseClassB也变得抽象,因此不能从中创建对象)。
向函数中添加"=0"意味着它们是纯虚拟的,必须在子类中实现。这显然不是你想要的。如果从基类中具有实现的函数中除去"=0",则它应该按预期工作。