C ++实现扩展subInterfaces的子类,而不覆盖已覆盖的方法

时间:2014-02-19 20:06:15

标签: c++ inheritance abstract-class

我创建了扩展C ++中其他接口的接口(抽象类),我试图实现它们,但是在编译时会出现错误。

以下是错误:

main.cpp: In function 'int main()':
main.cpp:36:38: error: cannot allocate an object of abstract type 'Subclass'
     Subclass * subObj = new Subclass();
                                      ^
Subclass.h:13:7: note:   because the following virtual functions are pure within 'Subclass':
 class Subclass : SubInterface {
       ^
SuperInterface.h:13:18: note:   virtual void SuperInterface::doSomething()
     virtual void doSomething()=0;

以下是我的消息来源:

#include <iostream>

class SuperInterface {
public:
    virtual void doSomething() = 0;
protected:
    int someValue;
};

class SubInterface : public SuperInterface {
public:
    virtual void doSomethingElseThatHasNothingToDoWithTheOtherMethod() = 0;
protected:
    int anotherValue;
};

class Superclass : public SuperInterface {
public:
    Superclass() {}
    virtual ~Superclass() {}
    void doSomething() {std::cout << "hello stackoverflow!";}
};

class Subclass : public SubInterface {
public:
    Subclass() {}
    virtual ~Subclass() {}
    void doSomethingElseThatHasNothingToDoWithTheOtherMethod() {std::cout << "goodbye stackoverflow!";}

};

int main(void)
{
    Superclass * superObj = new Superclass();
    Subclass * subObj = new Subclass();
}

这就是我想要的: 我希望我的实现能够识别,因此具有与已经覆盖的方法相同的行为(例如,subObj->doSomething()方法无需再次实现它就可以工作)。任何人都可以告诉我,如果可能的话,我应该做些什么来实现这一目标?感谢。

5 个答案:

答案 0 :(得分:2)

您收到错误是因为您正在尝试创建抽象类的对象。 由于此行Subclass,您的void doSomethingElse()=0;是一个抽象类。 如果一个类有一个纯虚函数,它将是一个抽象类。你不能创建一个抽象类的对象,你只能有一个引用或指向它的指针。

要摆脱错误,doSomethingElseSubclass的声明应为

void doSomethingElse();

而不是void doSomethingElse()=0;

此外,我不明白为什么你需要两个接口。您可以从Subclass派生SuperInterface,因为它基本上与SubInterface

相同

答案 1 :(得分:2)

不,你不能通过简单的继承做你想做的事。 Subclass在任何时候都不会继承或提供doSomething()的实现,因此您无法根据需要调用subObj->doSomething()。您必须遵守subInterface

的接口合同

您可以从SubclassSuperclass继承Subinterface,只需将doSomething()实现为一种代理Superclass::doSomething()。你仍然需要一个实现,但你不必“重新实现”它。

答案 2 :(得分:0)

你的类'Subclass'应该覆盖2个纯虚方法,所以:

class Subclass : SubInterface {
public:
    Subclass();
    virtual ~Subclass();
    void doSomethingElse() override;
    void doSomething() override;
};

不这样做或说明

  

void doSomethingElse()= 0;

class Subclass也变得抽象,无法实例化。您可以查看:http://www.parashift.com/c++-faq-lite/pure-virtual-fns.html

  

这就是我想要的:我希望我的实现能够意识到这一点   与已经覆盖的方法相同的行为(例如   subObj-&gt; doSomething()方法无需实现即可运行   再次)。任何人都可以告诉我如果要做到这一点我应该做些什么   它甚至可能!! ??感谢。

- &GT;也许声明方法虚拟而不是虚拟

答案 3 :(得分:0)

说实话,我并非完全确定您的设计想要表达的内容,但此处至少存在两个技术错误:

1。)在所有情况下都使用私有继承,因此您实际上根本不处理“接口”。公共继承是这样实现的:

class SubInterface : public SuperInterface

2。)您使用=0来表示您想要实现的功能。

这将修复编译器错误,但设计仍然值得怀疑。考虑到你在问题结束时给出的动机,我推荐组合而不是(公共)继承。在C ++中,共享功能最好用组合表达。简而言之,将常用功能封装在一个单独的类中,并为其他类配备一个对象。

class CommonFunctionality
{
//...
public:
    void doSomething();
    void doSomethingElse();
};

class SuperClass
{
//...
private:
    CommonFunctionality m_functionality;
};

class SubClass : public SuperClass
{
//...
private:
    CommonFunctionality m_functionality;
};

事实上,也许你甚至不需要 来为CommonFunctionality创建一个类。也许简单的独立功能会做。具有Java背景的程序员(并且您的代码看起来有点像)倾向于将太多东西放入类中而不是C ++中所需的东西。

答案 4 :(得分:0)

有两个问题,编译器明确说明了这些问题:

问题1

SubInterface::doSomethingElse()()中的{p> Subclass被声明为纯虚拟,无视您尝试在源文件中定义它(我很确定,这是一种复制粘贴错误)。< / p>

class Subclass : SubInterface
{
public:
    Subclass();
    virtual ~Subclass();
    void doSomethingElse() = 0; // still pure? 
};

解决方案很明显:


class Subclass : SubInterface
{
public:
    Subclass();
    virtual ~Subclass();
    virtual void doSomethingElse() override 
    {   
    }

};

(这里使用C ++ 11 override说明符,因此编译器将检查覆盖的正确性;它不是强制性的)

问题2

doSomething()甚至没有尝试覆盖,无论是SuperInterface还是Subclass,所以它都保持纯虚拟。虽然在doSomething()中覆盖了Superclass,但Subclass却不知道Superclass的存在。

enter image description here

解决方案:覆盖doSomething()SuperInterfaceSubclass的任何子项中的Subclass(尚未拥有它们)。例如,覆盖Subclass


class Subclass : SubInterface
{
public:
    Subclass();
    virtual ~Subclass();
    virtual void doSomething() override 
    {   
    }

    virtual void doSomethingElse() override 
    {   
    }

};

其他问题:

  • 您正在继承没有可见性说明符,即privat ely。使用public继承直到您确实需要其他内容:

    class Derved : public Base {};
    
  • 您的源文件扩展名为.c,但包含C ++代码。如果您没有通过命令行参数明确声明编程语言,这可能会使一些编译器感到困惑。按照惯例,大多数程序员使用.cpp扩展名,大多数编译器将这些文件视为C ++源文件。