C++ 强制派生类而不再次实现纯虚拟

C++ 强制派生类而不再次实现纯虚拟,c++,inheritance,object-design,C++,Inheritance,Object Design,我定义了一个接口类A,它定义了一些基本函数。在我的实现中,我有一个基类A0,它实现了这个接口,我从这个基类派生了层次结构中的几个其他类 #include <iostream> #include <string> class IContainer { public: IContainer() {}; virtual ~IContainer() {}; virtual void loadDefaults() = 0; virtual voi

我定义了一个接口类
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;
}
但是,如果我从
IContainer
中导出
IContainerReader
,我会得到以下错误:

||=== Build: Debug in CPPMingW (compiler: GNU GCC Compiler) ===|
D:\src\c\Tests\CPPMingW\main.cpp||In function 'int main(int, char**)':|
D:\src\c\Tests\CPPMingW\main.cpp|78|error: cannot declare variable 'r' to be of abstract type 'CSVReader'|
D:\src\c\Tests\CPPMingW\main.cpp|58|note:   because the following virtual functions are pure within 'CSVReader':|
D:\src\c\Tests\CPPMingW\main.cpp|11|note:     virtual void IContainer::loadDefaults()|
D:\src\c\Tests\CPPMingW\main.cpp|12|note:     virtual void IContainer::storeDefaults()|
D:\src\c\Tests\CPPMingW\main.cpp|14|note:     virtual bool IContainer::open()|
D:\src\c\Tests\CPPMingW\main.cpp|15|note:     virtual bool IContainer::close()|
D:\src\c\Tests\CPPMingW\main.cpp|79|error: cannot declare variable 'w' to be of abstract type 'CSVWriter'|
D:\src\c\Tests\CPPMingW\main.cpp|67|note:   because the following virtual functions are pure within 'CSVWriter':|
D:\src\c\Tests\CPPMingW\main.cpp|11|note:     virtual void IContainer::loadDefaults()|
D:\src\c\Tests\CPPMingW\main.cpp|12|note:     virtual void IContainer::storeDefaults()|
D:\src\c\Tests\CPPMingW\main.cpp|14|note:     virtual bool IContainer::open()|
D:\src\c\Tests\CPPMingW\main.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;
}
#包括
#包括
I类容器
{
公众:
i容器(){};
虚拟~IContainer(){};
虚拟void loadDefaults()=0;
虚拟void storeDefaults()=0;
虚拟bool open()=0;
虚拟布尔关闭()=0;
};
类IContainerReader:虚拟公共IContainer
{
公众:
IContainerReader(){};
虚拟~IContainerReader(){};
虚拟布尔读取()=0;
};
类IContainerWriter:虚拟公共IContainer
{
公众:
IContainerWriter(){};
虚拟~IContainerWriter(){};
虚拟bool write()=0;
};
类容器基:虚拟公共IContainer
{
公众:
ContainerBase(){}
虚拟~ContainerBase(){}
void loadDefaults(){}
void storeDefaults(){}
};
CSVBase类:公共容器库
{
公众:
CSVBase(){}
虚拟~CSVBase(){}
void setFilename(){}
bool open(){return true;}
bool close(){return true;}
};
CSVReader类:公共CSVBase、公共IContainerReader
{
公众:
CSVReader(){}
虚拟~CSVReader(){}
bool read(){return true;}
};
CSVWriter类:公共CSVBase、公共IContainerWriter
{
公众:
CSVWriter(){}
虚拟~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();
返回0;
}

对我来说,多元性是一个危险信号。您的CSVReader是IContainerReader和CSV Container?我希望CSVReader读取一个(csv)文件,解析它,然后输出一个CSVContainer对象。这个项目要大得多,但显然我不能发布数千行。这就是SSCE的要点。我的评论是关于代码是如何使用的,我不需要更多的代码;)与“因为我想确保读写器也总是有容器基础”相关。也许“容器”这个词在这里是错的,因为在我的上下文中,容器指的是一个可以保存(列)数据的对象。CSV只是一个例子,还有其他容器,我不想一次又一次地重新实现公共功能。我已经在Java中做了这个项目,并且找到了一个方法,即使它在基类中。显然,C++中不是这样的,所以我想知道是否有更优雅的方式。我可以让
Reader/Writer
返回一个基本对象,如果没有其他选择,这将是我首选的解决方案。Thx!我不知道派生也可以是虚拟的:)
#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;
}