虚拟基类函数中派生类的大小



>请考虑以下代码

class A {
int x, y;
public:
A(){}
virtual void PrintSize(){ cout << sizeof(typeof(*this)) << endl; }
};
class B : public A {
int a, b, c;
public:
B(){}
};
int main() {
A obja;
B objb;
obja.PrintSize();
objb.PrintSize();
}

"PrintSize((" 的目的是获取我们调用它的当前类的大小。发生的情况是,this-关键字引用类 A,即使我们从 B 调用它。我们不希望这样,因为我们需要这个函数对子类是通用的。

我们显然可以逐字重新定义每个类的函数。代码将变得更加难以处理,因为有太多不合时宜的行。更不用说将函数重写到每个类会破坏首先派生它的目的。

这是我的临时修复:

class A {
public:
virtual void PrintSize(){ cout << sizeof(typeof(*this)) << endl; }
};
class B : public A {
public:
virtual void PrintSize(){ cout << sizeof(typeof(*this)) << endl; }
};
class C : public A {
public:
virtual void PrintSize(){ cout << sizeof(typeof(*this)) << endl; }
};
class D : public A {
public:
virtual void PrintSize(){ cout << sizeof(typeof(*this)) << endl; }
};

虽然接受的答案可能已经解决了眼前的问题,但你突然没有了BC的共同基类。它们继承自两个不相关的类,即A<B>A<C>

另一种方法是创建一个定义接口的公共基(下面称为Interface(,并在派生类和接口之间添加 CRTP 类模板。这使您可以保留对Interface的指针和引用,并使用这些指针和引用调用virtual成员函数。

下面是在vector中存储指向公共基类的指针的示例:

#include <iostream>
#include <memory>
#include <vector>
struct Interface {
virtual ~Interface() = default;
virtual void PrintSize() const = 0;
virtual void do_stuff() const = 0;
};
template<typename T>
struct Printer : public Interface {
void PrintSize() const override {
std::cout << sizeof(T) << 'n';
}
};
class B : public Printer<B> {
int a{};
public:
void do_stuff() const override { std::cout << "B doing stuffn"; }
};
class C : public Printer<C> {
int a{}, b{}, c{};
public:
void do_stuff() const override { std::cout << "C doing stuffn"; }    
};
int main() {
std::vector<std::unique_ptr<Interface>> objs;
objs.emplace_back(std::make_unique<B>());
objs.emplace_back(std::make_unique<C>());
for(auto& ptr : objs) {
ptr->do_stuff();
ptr->PrintSize();
}
}

可能的输出:

B doing stuff
16
C doing stuff
24

您可以使用 CRTP 习惯用法来执行此操作。 https://eli.thegreenplace.net/2011/05/17/the-curiously-recurring-template-pattern-in-c 这个想法是父类是一个模板,因此您可以直接在其中访问子类的类型。 这样,您将能够从子类中删除所有"打印大小"。

例:

template <typename Derived>
class A {
int x, y;
public:
A() {}
void PrintSize() { cout << sizeof(Derived) << endl; }
};
class B : public A<B> {
int a, b, c;
public:
B() {}
};
class C : public A<C> {
public:
C() {}
};
int main() {
C objc;
B objb;
objc.PrintSize();
objb.PrintSize();
}

输出为:

8

20

最新更新