【问题标题】:Use pure virtual methods in an abstract class在抽象类中使用纯虚方法
【发布时间】:2013-05-07 10:42:40
【问题描述】:
#ifndef TEST_H
#define TEST_H
#include <iostream>
#include <string>
class A{
public:
    virtual void test1() = 0;
    virtual std::string test2() = 0;
};

class B : public A{

public:
     void test1(){
       std::cout << A::test2() << " World";
    }
};
class C : public B{
public:
     std::string test2(){
        return "hello";
    }
};
class C1 : public B{
public:
     std::string test2(){
        return "Sup";
    }
};

#endif // TEST_H

我有一个只有纯虚方法的接口 A。我有一个抽象类想要实现test1 并使用test2 来实现test1

现在是 C 和 C1 以及我实现 test2 的具体类

但我不能在 B 类做std::cout &lt;&lt; A::test2() &lt;&lt; " World";

错误:无法调用成员函数'virtual std::string A::test2()' 没有对象

我如何在 c++ 中做这样的事情?

【问题讨论】:

  • AB 根本不相关。所以你不能那样做。为了能够做到这一点B 需要从A 继承,我不确定这是否适合您的设计。
  • 一个类要实现A的接口,实际上需要继承A
  • 是的,很抱歉打错了。

标签: c++


【解决方案1】:

不要纠结于纯虚拟与虚拟。 A 中声明的两个函数都是虚函数,您可以将它们视为虚函数。所以Btest1 的实现应该简单地调用test2。没有A:: 限定符。这会进行一次虚拟调用,最终会以最派生的test2 版本结束,即CC1 中定义的版本,具体取决于对象的类型。在我从A::test2() 中删除A:: 之后,以下代码可以正常工作(应该如此):

int main() {
    C c;
    c.test1();
    C1 c1;
    c1.test1();
    return 0;
}

[work]$ g++ test.cpp
[work]$ ./a.out
hello WorldSup World[work]$ 

是的,您应该在输出中添加\n&lt;g&gt;

【讨论】:

    【解决方案2】:

    您的class B 需要从class A 继承。

    class B: public A ... 
    

    当然,调用A::test2() 是行不通的,因为该类没有实现——它没有主体。您也可以通过在 A 类中实现它来解决这个问题,如下所示:

    std::string A::test2() { return "some string"; }
    

    【讨论】:

    • 这应该是一个内联纯虚函数吗?标准不允许内联纯虚函数。您需要在类主体之外定义它。
    • 真的吗?我从未使用过“实现的纯虚拟”,但我认为您可以内联它们。但我会编辑它。
    • 我现在很困惑。您能否更清楚地说明我必须做什么?
    • 如果你想在B中使用A::test2(),那么你需要实现A::test2(),让它有一个真正的函数——调用一个纯虚函数是行不通的。如果你想调用“当前派生的test2”,那么你不应该有A::。无论如何,您确实需要从 A 类派生 B 类。
    【解决方案3】:

    如果您想要虚拟调用,请不要使用显式范围限定。使用A::test2 将尝试调用A::test2,而不使用动态调度。反过来,这将无法链接,因为 A::test2 没有实现。

    【讨论】:

    • 所以你说的是我只是调用 test2();而不是 A::test2(); ?我得到了同样的结果。
    • 当我真正尝试这个时,我得到了完全不同的结果。特别是,您的初始代码编译但无法链接(链接器抱怨它找不到 A::test2 的实现)。如果我删除 A::,它会编译并正确运行。所以要么你使用了一个非常有问题的编译器,要么你实际上并没有发布你正在使用的代码。你在某处有流浪static吗?
    • 好的哇嗯。我使用了 GCC 4.8,它引发了一些错误。但它在clang中编译得很好。
    • @CharlesBailey 是的,我也发现了这一点。修正了答案。
    【解决方案4】:

    错误信息暗示,当你编译它时,B 没有从A 继承,所以没有A 类型的对象可以调用成员函数。您发布的代码给了我一个不同的错误:A::test2 未定义。

    几乎可以肯定,您想虚拟调用该函数(即在 CC1 或其他任何地方调用最终覆盖)。在那种情况下,根本不要限定它:

    std::cout << test2() << std::endl;
    

    您的代码尝试专门调用A 中声明的版本,而不是任何覆盖。如果这实际上是您想要的(我对此表示怀疑),那么需要定义该函数:

    std::string A::test2() {
        return "I'm a pure virtual function. Why are you calling me?";
    }
    

    请注意,由于语言的一个怪癖,纯虚函数不能在类定义中定义;这个定义必须在课堂之外。

    【讨论】:

      猜你喜欢
      • 2012-10-01
      • 1970-01-01
      • 2015-07-13
      • 2019-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-14
      • 2021-06-30
      相关资源
      最近更新 更多