我在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);
但我真的不喜欢它。
还有其他解决方案吗? setId/getId
中不需要来自struct A
的{{1}}个方法。我刚做了继承,因为我需要AB
以及foo()
中的其他内容,但所有其他方法都是唯一的。
答案 0 :(得分:7)
既然你说你不需要A
这些方法的版本,你可以写
struct AB : public A, public B
{
void foo() override {}
void foo2() override {}
using B::setId;
using B::getId;
};
这会将B
的这些方法的实现放入AB
的命名空间,并使它们明确地调用它们。
答案 1 :(得分:2)
包装器转发方法怎么样:
struct AB : public A, public B
{
public:
void setAId(int i) { A::setID(i); }
void setBId(int i) { B::setID(i); }
};
这样你就不会成为受害者"名称隐藏,您的意图在代码中变得清晰,并且您的名称反映了他们的行为,并且您不需要明确地访问基类成员。
或者,您可以创建另一个基类,并在A
和B
中虚拟地继承它,其中包含setId
方法。
答案 2 :(得分:1)
我相信我和接受的答案都引入了相当恼人的问题,请考虑:
AB ab;
A *a = &ab;
a->setId(10); //problem
a->foo(); //calls AB::foo() correctly
当使用名称隐藏(接受的答案)时,AB
对象永远不会被调用,而我的回答(包裹调用)也不会解释这一点。在我看来,在这种情况下正确的方法是使用private
A
的{{1}}并且只展示foo()
,因此只有一件事会改变原始OP的代码:
struct AB : private A, public B
答案 3 :(得分:1)
只要您在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); }
};
答案 4 :(得分:0)
通常使用OO和继承,如果当时未知功能重用,通常最好多次实现该功能,直到确定一个允许您将其分开的模式为止。
例如,将类对象作为数据容器并从中继承是没有错的。
class IdentificationData {
int ID;
. . .
}
您也不一定需要将函数作为类的一部分。类只是一个容器,用于组织和封装数据,可以对数据进行操作的函数或函数集合到一个公共集合中。
class IdentificationFunctionality{
static SetID( IdentificationData* obj) {...}
}
这样做可以让你做类似......
的事情class AB: IdentificationData, B {
. . .
}
AB* ab = new AB();
IdentificationFunctionality::SetID(&ab);
这样做的另一个好处是,这将允许您在不需要了解数据银行系统的详细信息的情况下进行一些簿记。