强制派生类而不再次实现纯虚函数
Force a derived class without implementing pure virtuals again
我定义了一个接口类A
,它定义了一些基本函数。在我的实现中,我有一个基类A0
,它实现了这个接口,从这个基类中,我派生了几个层次结构中的其他类。
#include <iostream>
#include <string>
class IContainer
{
public:
IContainer() {};
virtual ~IContainer() {};
virtual void loadDefaults() = 0;
virtual void storeDefaults() = 0;
virtual bool open() = 0;
virtual bool close() = 0;
};
class IContainerReader
{
public:
IContainerReader() {};
virtual ~IContainerReader() {};
virtual bool read() = 0;
};
class IContainerWriter
{
public:
IContainerWriter() {};
virtual ~IContainerWriter() {};
virtual bool write() = 0;
};
class ContainerBase : public IContainer
{
public:
ContainerBase() {}
virtual ~ContainerBase() {}
void loadDefaults() {}
void storeDefaults() {}
};
class CSVBase : public ContainerBase
{
public:
CSVBase() {}
virtual ~CSVBase() {}
void setFilename() {}
bool open() { return true; }
bool close() { return true; }
};
class CSVReader : public CSVBase, public IContainerReader
{
public:
CSVReader() {}
virtual ~CSVReader() {}
bool read() { return true; }
};
class CSVWriter : public CSVBase, public IContainerWriter
{
public:
CSVWriter() {}
virtual ~CSVWriter() {}
bool write() { return true; }
};
int main(int argc, char *argv[])
{
CSVReader r;
CSVWriter w;
IContainerReader *ir = &r;
IContainerWriter *iw = &w;
ir->open();
iw->open();
ir->read();
iw->write();
ir->close();
iw->close();
return 0;
}
可以看到,我定义了一个IContainerReader
和一个IContainerWriter
类,它们定义了只与各自的实现相关的特殊函数。
但是现在我有一个问题,因为我想确保Reader或writer也总是具有容器基础。因此,合乎逻辑的解决方案是由IContainer
导出IContainerReader/-Writer
。但是当我这样做时,编译器会抱怨,因为它期望现在Reader/Writer
对象也实现了基函数,这些函数已经通过基类定义了。但是,如果我让IContainerReader
不从IContainer
派生,则指向这些对象之一的指针也不能保证具有IContainer
的功能。
如果我尝试像这样编译它,我会得到错误,因为IContainerReader
不是IContainer
||=== Build: Debug in CPPMingW (compiler: GNU GCC Compiler) ===|
D:srccTestsCPPMingWmain.cpp||In function 'int main(int, char**)':|
D:srccTestsCPPMingWmain.cpp|83|error: 'class IContainerReader' has no member named 'open'|
D:srccTestsCPPMingWmain.cpp|84|error: 'class IContainerWriter' has no member named 'open'|
D:srccTestsCPPMingWmain.cpp|89|error: 'class IContainerReader' has no member named 'close'|
D:srccTestsCPPMingWmain.cpp|90|error: 'class IContainerWriter' has no member named 'close'|
||=== Build failed: 4 error(s), 0 warning(s) (0 minute(s), 5 second(s)) ===|
然而,如果我从IContainer
中导出IContainerReader
,我得到以下错误:
||=== Build: Debug in CPPMingW (compiler: GNU GCC Compiler) ===|
D:srccTestsCPPMingWmain.cpp||In function 'int main(int, char**)':|
D:srccTestsCPPMingWmain.cpp|78|error: cannot declare variable 'r' to be of abstract type 'CSVReader'|
D:srccTestsCPPMingWmain.cpp|58|note: because the following virtual functions are pure within 'CSVReader':|
D:srccTestsCPPMingWmain.cpp|11|note: virtual void IContainer::loadDefaults()|
D:srccTestsCPPMingWmain.cpp|12|note: virtual void IContainer::storeDefaults()|
D:srccTestsCPPMingWmain.cpp|14|note: virtual bool IContainer::open()|
D:srccTestsCPPMingWmain.cpp|15|note: virtual bool IContainer::close()|
D:srccTestsCPPMingWmain.cpp|79|error: cannot declare variable 'w' to be of abstract type 'CSVWriter'|
D:srccTestsCPPMingWmain.cpp|67|note: because the following virtual functions are pure within 'CSVWriter':|
D:srccTestsCPPMingWmain.cpp|11|note: virtual void IContainer::loadDefaults()|
D:srccTestsCPPMingWmain.cpp|12|note: virtual void IContainer::storeDefaults()|
D:srccTestsCPPMingWmain.cpp|14|note: virtual bool IContainer::open()|
D:srccTestsCPPMingWmain.cpp|15|note: virtual bool IContainer::close()|
||=== Build failed: 2 error(s), 0 warning(s) (0 minute(s), 6 second(s)) ===|
所以编译器希望我在派生类中也从基类中补充所有的函数。
那么有没有解决方案,而不必在Reader/Writer类中再次定义所有这些函数?当然,我可以实现只到基类的假人,但我认为这有点笨拙和不必要的开销,我希望可能有一个更好的解决方案。
希望我没记错。你有一种钻石问题。您可以通过两条路径继承IContainer
。
通常在这种情况下,每个CSVReader
实例创建两个IContainer
实例,并且对IContainer
方法的调用将是模糊的。在您的示例中,通过IContainerReader
的路径没有定义上述函数。虚拟继承使得只创建一个实例。
来自IContainer
的继承应该声明为virtual
。虚拟继承使得类的每个派生"将组合在一起"(抱歉不是很专业的术语,但这就是我在简单英语中的理解)。在您的示例中,将为两个路径只创建一个IContainer
副本,并且将从两个路径填充vtable
s。
以下代码编译:
#include <iostream>
#include <string>
class IContainer
{
public:
IContainer() {};
virtual ~IContainer() {};
virtual void loadDefaults() = 0;
virtual void storeDefaults() = 0;
virtual bool open() = 0;
virtual bool close() = 0;
};
class IContainerReader : virtual public IContainer
{
public:
IContainerReader() {};
virtual ~IContainerReader() {};
virtual bool read() = 0;
};
class IContainerWriter : virtual public IContainer
{
public:
IContainerWriter() {};
virtual ~IContainerWriter() {};
virtual bool write() = 0;
};
class ContainerBase : virtual public IContainer
{
public:
ContainerBase() {}
virtual ~ContainerBase() {}
void loadDefaults() {}
void storeDefaults() {}
};
class CSVBase : public ContainerBase
{
public:
CSVBase() {}
virtual ~CSVBase() {}
void setFilename() {}
bool open() { return true; }
bool close() { return true; }
};
class CSVReader : public CSVBase, public IContainerReader
{
public:
CSVReader() {}
virtual ~CSVReader() {}
bool read() { return true; }
};
class CSVWriter : public CSVBase, public IContainerWriter
{
public:
CSVWriter() {}
virtual ~CSVWriter() {}
bool write() { return true; }
};
int main(int argc, char *argv[])
{
CSVReader r;
CSVWriter w;
IContainerReader *ir = &r;
IContainerWriter *iw = &w;
ir->open();
iw->open();
ir->read();
iw->write();
ir->close();
iw->close();
return 0;
}
- 在命名空间内部还是外部实现 c++ 函数?
- 如何在C++中实现函数(f)(x)(y, z)(g)(r)
- 如何在C++中实现函数上的二叉搜索?
- 键按下事件错误 Qt 实现函数时
- 在子类之外实现函数导致未知错误
- 通过模板滥用实现函数式C++
- C++,实现函数"int next(std::string param)"时出现奇怪的编译器错误
- 我正在尝试创建自己的 strcat() 函数,而不是使用库实现函数<cstring>
- 如果未实现函数,则在链接时启用错误
- 用函数参数实现c++函数指针
- 如何在Android SDK中调用和实现C++函数
- 在 C++ RCPP 中实现 R 函数
- 实现函数模板填充多维对象
- 类的层次结构,试图在基本级别实现函数
- 用c++实现函数对象的自动检测类型
- 用shared_ptrs实现函数模板的C++实例化
- 在类中实现函数导致错误:成员引用基类型'ifstream (string)'不是结构或联合
- 用c++实现S函数.生成错误
- 引用可以用于实现函数重写吗
- 如何在c++中实现函数超时