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

C++ C++;多重继承-相同的方法名-我可以删除其中一个吗?,c++,c++11,inheritance,C++,C++11,Inheritance,我在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() =

我在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 A
的方法
setId/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); }
};
这样,您就不会成为名称隐藏的“受害者”,您的意图在代码中变得清晰,您的名称反映了它们的功能,您不需要显式地访问基类的成员


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

我相信我的答案和公认的答案都会带来相当烦人的问题,请考虑:

AB ab;
A *a = &ab;
a->setId(10); //problem
a->foo(); //calls AB::foo() correctly
当使用名称隐藏(接受的答案)时,
AB
对象永远不会被调用,而我的答案(包装调用)也不会对此进行解释。在我看来,在这种情况下,正确的方法是使用
private
不存在
A
并只公开
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);

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

只要您在AB类型的对象或AB指针上调用
setId(int)
,接受的答案就会起作用(大多数情况下,肯定是这样)。但是如果您想调用
A*ab=new ab()上的函数必须显式重写它

结构A{ 国际开发协会; 虚空setId(inti){idA=i;} }; 结构B{ 国际开发银行; 虚空setId(inti){idB=i;} }; 结构AB:公共A,公共B { void setId(inti)重写{B::setId(i);} };
您可以修改您的层次结构吗?例如,更改
A
并引入额外的classes@VittorioRomeo当你说你“需要”
foo()
a
中的其他东西时,我可以(以有限的方式),你指的是声明或定义吗?可以将类a分解成其他东西。这会起作用,但仍有人可以调用setId()并获取错误。@MartinPerry,那么它应该在基类imo中受到保护。@pressureCtion它将是不正确的,因为其他类只从A继承,或者只从B继承,所以它们可以调用这些类methods@MartinPerry如果在继承中有不需要的公共方法,那么应该在实际要继承的基类和其他基类中进行组合或拆分。这样,两种情况都会起作用。名称隐藏确实不应该用于此目的。此方法的一个问题是,
A::setId
在这种情况下仍将被调用:
A*ab=new ab();ab->setId(0)