C++多重继承 - 相同的方法名称 - 我可以以某种方式删除其中一个吗?

C++ multiple inheritance - same method names - can I somehow remove one of them?

本文关键字:删除 一个 方式 多重继承 方法 C++ 我可以      更新时间:2023-10-16

我在 C++11 中有这个结构

struct A {
int idA;   
void setId(int i) { idA = i;}
int getId() { return idA;}
virtual void foo() = 0;
};
struct B {
int idB;   
void setId(int i) { idB = i;}
int getId() { return idB;}
virtual void foo2() = 0;
};
struct AB : public A, public B
{
void foo() override {}
void foo2() override {}
};

现在在主要我可以这样称呼它:

AB * ab = new AB();
ab->B::setId(10);

但我真的不喜欢它。

还有其他解决方案吗?AB中不需要从struct AsetId/getId的方法。我只是做了继承,因为我需要foo()和其他东西来自A,但所有其他方法都是唯一的。

既然你说你不需要这些方法A的版本,你可以写

struct AB : public A, public B
{
void foo() override {}
void foo2() override {}
using B::setId;
using B::getId;
};

这会B将这些方法的实现放入AB的命名空间中,并使调用它们变得明确。

包装器转发方法怎么样:

struct AB : public A, public B
{
public:
void setAId(int i) { A::setID(i); }
void setBId(int i) { B::setID(i); }
};

这样,您就不会成为名称隐藏的"受害者",您的意图在代码中变得清晰,并且您拥有反映其作用的名称,并且您不需要显式访问基类的成员。

或者,您可以创建另一个基类,并在包含setId方法的AB中虚拟继承它。

只要您在 AB 或 AB 指针类型的对象上调用setId(int),接受的答案就有效(当然,大多数情况下)。但是,如果要在A* ab = new AB();上调用该函数,则必须显式覆盖它。

struct A {
int idA;   
virtual void setId(int i) { idA = i;}
};
struct B {
int idB;   
virtual void setId(int i) { idB = i;}
};
struct AB : public A, public B
{
void setId(int i) override { B::setId(i); }
};

我相信我的答案和接受的答案都引入了相当烦人的问题,请考虑:

AB ab;
A *a = &ab;
a->setId(10); //problem
a->foo(); //calls AB::foo() correctly

当使用名称隐藏(接受答案)时,AB对象永远不会被调用,而我的答案(包装调用)也没有考虑到这一点。在我看来,在这种情况下,正确的方法是使用A的不确定性private并且只公开foo(),因此只有一件事会与原始OP的代码相比有所改变:

struct AB : private A, public B

通常,对于 OO 和继承,如果当时功能重用未知,通常最好多次实现该函数,直到确定允许您将其分解的模式。

例如,将类对象作为数据的容器并从中获取并没有错。

class IdentificationData {
int ID;
. . .
}

您也不一定需要将函数作为类的一部分。类只是一个容器,用于组织和封装数据、可以对数据进行操作的函数或函数集合到一个公共集中。

class IdentificationFunctionality{
static SetID( IdentificationData* obj) {...}
}

这样做将允许您执行类似操作...

class AB: IdentificationData, B {
. . .
}
AB* ab = new AB();
IdentificationFunctionality::SetID(&ab);

这样做的另一个好处是,这将允许您进行一些簿记,而无需您的对象知道数据库系统的详细信息。