提问人:Mike Eager 提问时间:9/4/2023 最后编辑:Mike Eager 更新时间:9/5/2023 访问量:97
从另一个派生类调用派生类中的成员函数
Call member function in derived class from another derived class
问:
我有一个程序,它有一个基类和几个派生类,这些派生类包含覆盖基类成员函数的成员函数。派生类之间存在一些重复的代码,我想消除这些重复。具体而言,在其中一个派生类中,一个成员函数包含一些初始处理,然后与另一个派生类中的同一命名成员函数进行相同的处理。
下面是一个简化的示例:
#include <iostream>
class BASE
{
public:
virtual ~BASE() = default;
virtual void A() { std::cout << "In BASE\n"; }
virtual void B() { std::cout << "Shared by all instances\n"; }
virtual void C() { std::cout << "Different in all instances\n"; }
};
class D1: BASE
{
public:
void A() override { std::cout << "In D1\n"; }
void C() override { std::cout << "In D1::C()\n"; }
};
class D2: BASE
{
public:
void A() override
{
std::cout << "In D2\n";
// #1
// D1::A(); // Error cannot call D1::A() w/o object
// #2
// D1 *t = (D1 *) this; // Creates recursive loop
// t->A(); // calling D2:A()
}
void C() override { std::cout << "In D2::C()\n"; }
};
int main()
{
D1 d1;
D2 d2;
BASE *b = &d1;
b->A();
b = &d2;
b->A();
}
在此示例中,我希望将 to 的调用链接到,以便我能看到来自两个成员函数的消息。我尝试了两种不同的方法来做到这一点(参见 #1 和 #2),它们都出错了。D2::A()
D1::A()
正确的方法是什么?
答:
-1赞
Wyck
9/4/2023
#1
首先,除非你声明.请注意 的用法。否则,你会得到类似“类型转换”的东西:从“D1 *”到“BASE *”的转换存在,但无法访问。(MSVC)BASE *b = &d1;
class D1: public BASE
public
此外,听起来需要从中派生,以便除了任何额外的功能之外,还可以调用其实现。这样,您就可以像您提到的那样,通过在实现的末尾显式调用 来“链接”。D2
D1
D2::A
D1::A
D1::A()
D2::A
#include <iostream>
class BASE
{
public:
virtual ~BASE() = default;
virtual void A() { std::cout << "In BASE\n"; }
};
class D1: public BASE
{
public:
void A() override { std::cout << "In D1\n"; }
};
class D2: public D1
{
public:
void A() override
{
std::cout << "In D2\n";
D1::A(); // Chain to D1::A
}
};
int main()
{
D1 d1;
D2 d2;
BASE *b = &d1;
b->A();
b = &d2;
b->A();
}
预期输出:
In D1
In D2
In D1
第一个“In D1”将来自呼叫,第二条和第三条消息“In D2, In D1”将来自呼叫,因为明确地“链接”到 .b = &d1; b->A();
b = &d2; b->A();
D2::A
D1::A
评论
0赞
Mike Eager
9/4/2023
D2 不是 D1 的适当子集;它只有一个成员函数,其代码在 D1 和 D2 中都是重复的。D1 和 D2 中的其他成员函数可能非常不同。
0赞
Mike Eager
9/5/2023
我编辑了这个例子,以明确 D1 和 D2 是独立的,不能相互推导。
评论
void A() override
using namespace std;
D2
D1
D2
D1
D1::A();
D2
D2
D1
main
b
new D2;
BASE
delete
Intermediate1
BASE
D1
D2
D1
D2
Intermediate1