【问题标题】:C++ inheritance & virtual function problemC++继承和虚函数问题
【发布时间】:2020-07-17 06:47:08
【问题描述】:

我想显示结果是 2。(现在结果是 1。)

我该怎么办? (我想调用 B::test()。但实际上代码无法访问 main.c 中的 b.h、b.c)

我还想知道 a.h 中从“public: virtual int test() {return 1;}”到“protected: virtual int test() {return 1;}”的错误

继承关系是 超A类 亚B类 超类A 子类C

但我可以访问 main.c 中的 A 类 我想要结果 2。(“a.test()”无法调用“b.test()”)

// a.h
#ifndef _A_
#define _A_

class A {
    public:
        A() {};
        ~A() {};
    //protected:
        virtual int test() {return 1;}
    private:
        friend class B;
};

#endif
// b.h
#ifndef _B_
#define _B_
#include "a.h"

class B : public A {
    public:
        B() {};
        ~B() {};
    private:
        int test() override;
        friend class A;
};

#endif
// b.c
#include "b.h"

int B::test()
{
    return 2;
}
// c.h
#ifndef _C_
#define _C_
#include "a.h"

class C : public A {
    public:
        C() {};
        ~C() {};
    private:
        int test() override;
        friend class A;
};

#endif
// c.c
#include "c.h"

int C::test()
{
    return 3;
}
// main.c
#include <iostream>
#include "a.h"

using namespace std;

int main(void)
{
    A *a = new A();
    cout << a->test() << "\n";
    return 0;
}

【问题讨论】:

  • 我建议更改您的标题和标签。这不是多重继承。多重继承是类有两个 immediate 父级的地方:class C : public A, public B ...
  • 代码无法访问 main.c 中的 b.h, b.c 为什么会这样?
  • 我只贴了实际代码问题的总结。

标签: c++


【解决方案1】:

创建B 类型的对象,你仍然可以调用test 方法,因为A::test 是公共的。此代码将打印 2:

int main(void)
{
    A *a = new B();
//             ^
    cout << a->test() << "\n";
    delete a;  // (1)
    return 0;
}

除非您将A 的析构函数设为虚拟(When to use virtual destructors?),否则第 (1) 行也无法正常工作:

class A {
    public:
        A() {};
        virtual ~A() {};
//      ^^^^^^^
    //protected:
        virtual int test() {return 1;}
    private:
        friend class B;
};

UPD如果由于某种原因您不能包含b.h,您可以执行以下操作:

a.h:

#ifndef _A_
#define _A_

class A {
    ...
};

A* CreateB();

#endif

a.c:

#include "a.h"
#include "b.h"

...

A* CreateB() {
    return new B();
}

main.c:

#include <iostream>
#include "a.h"

using namespace std;

int main(void)
{
    A *a = CreateB();
    cout << a->test() << "\n";
    delete a;
    return 0;
}

【讨论】:

  • main.c 无法访问 B 类和 C 类(b.h, b.c, c.h, c.c)。
  • @AndrewChang 添加了如何处理它的示例
  • 感谢您的建议。但是不起作用... /tmp/ccrGMeiu.o:在函数A::A()': main.c:(.text._ZN1AC2Ev[_ZN1AC5Ev]+0xb): undefined reference to vtable for A'collect2:错误:ld返回1退出状态
【解决方案2】:

考虑你的代码:

// main.c
#include <iostream>
#include "a.h"

using namespace std;

int main(void)
{
    A *a = new A();
    cout << a->test() << "\n";
    return 0;
}

行为的关键决定者是=new A()

如果您将其更改为 =new B(),那么您将得到您想要的 '2' 的结果。

但是,您已经添加了限制“代码无法访问 b.h”。这意味着=new B() 不会编译。这个限制从何而来?您可以使用极其复杂的工厂模式来实现这一点,但这似乎不太可能是您想要做的。

访问说明符(privateprotectpublic)对于层次结构中的每个级别的相同方法(在本例中为test())都应该相同。这不是由编译器绝对强制执行的,而是一个明确的最佳实践。她在制作test() privateprotected 之间几乎没有区别,但在这两种情况下,表达式:

a->test()  

main 会失败,因为它在类之外,并且只能访问public 成员。

还值得指出的是,您的 friend 声明在所示代码中完全没有必要。

【讨论】:

  • 他的意思是 =new B() 不会编译。这个限制从何而来?您可以使用极其复杂的工厂模式来实现这一点,但这似乎不太可能是您想要做的。我会做。谢谢你的建议。
猜你喜欢
  • 2015-08-23
  • 1970-01-01
  • 1970-01-01
  • 2011-07-17
  • 2015-08-07
  • 2015-06-23
  • 1970-01-01
相关资源
最近更新 更多