C++ CRTP/宏/避免转换派生类的指针
最近我在一个项目中工作,我们遇到了一种情况,我们需要能够做这样的事情C++ CRTP/宏/避免转换派生类的指针,c++,pointers,multiple-inheritance,c-preprocessor,crtp,C++,Pointers,Multiple Inheritance,C Preprocessor,Crtp,最近我在一个项目中工作,我们遇到了一种情况,我们需要能够做这样的事情 #define TYPED(Type) \ virtual Type *typedThis() const { return (Type*) this; } class A { public: TYPED(A) virtual void describe() { std::cout << "I am type A\n"; } static int x; }; int A::x = 1; class
#define TYPED(Type) \
virtual Type *typedThis() const { return (Type*) this; }
class A {
public:
TYPED(A)
virtual void describe() { std::cout << "I am type A\n"; }
static int x;
};
int A::x = 1;
class B : public A {
public:
TYPED(B)
virtual void describe() { std::cout << "I am type B\n"; }
static int x;
};
int B::x = 2;
int
main(int argc, char** argv)
{
B* b = new B();
A* b2 = b;
b->describe();
b2->describe();
std::cout << b->typedThis()->x << std::endl;
std::cout << b2->typedThis()->x << std::endl; // AQUI DEBERIA DAR 2 !! :c
}
我发现真正有趣的是,virtual方法descripe()似乎按照我们想要的方式工作。因此,我可以推断方法typedThis()也在以我们希望的方式工作。但是如果是这样,为什么C++将这个指针看作是一个A*而不是一个B*。如果C++看到这个指针像一个B*,那么它就使用了正确的变量x.有人能给我解释一下吗?
我尝试过使用CRTP,但我不觉得这会让事情变得更简单,因为在这个项目中,我们将使用很多(很多)在它们之间不断派生的不同类,我看到了一些关于如何在具有多重继承时使用CRTP的文章,然而,它们确实很混乱,很难与我们目前所拥有的东西结合起来。我从示例中排除了所有干扰:
class A {
public:
virtual A *typedThis() const { return (A*) this; }
static int x = 1;
};
class B : public A {
public:
virtual B *typedThis() const { return (B*) this; }
static int x = 2;
};
int main()
{
B* b1 = new B;
A* b2 = b1;
std::cout << b1->typedThis()->x << "\n";
std::cout << b2->typedThis()->x << "\n";
}
还要注意的是,C样式转换会丢弃对象的限定符
const
。如果不是虚拟的,为什么应该是2?它将使用指针基类进行解析,而不是检查任何虚拟表来解析该函数。pba需要是虚拟的。是。因为这只是一个玩具示例,所以我使用了一个虚拟方法,只打印出一个数字。但在实际代码中,我们希望访问一些在类之间具有相同名称的属性。因此,假设A和B类都有int静态属性x。然后我们收到一个指针a*,但带有一个实例B的指针。如果我们想得到x的值。我们得到的是类A的x值,而不是类B的x值。在本例中,这相当于说,我们使用A的方法pba()而不是B的方法pba()打印。对x
的访问只使用表达式的类型,而不是实际值,因为它是类的属性而不是对象的属性。由于b->typedThis()
是一个b*
,因此您可以得到b::x
。但是,b2->typedThis()
是一个A*
,因此您可以得到A::x
。b2
指向aB
的事实并不重要。它并没有完全解决我的问题,但却是最有用的答案,谢谢!
class A {
public:
virtual A *typedThis() const { return (A*) this; }
static int x = 1;
};
class B : public A {
public:
virtual B *typedThis() const { return (B*) this; }
static int x = 2;
};
int main()
{
B* b1 = new B;
A* b2 = b1;
std::cout << b1->typedThis()->x << "\n";
std::cout << b2->typedThis()->x << "\n";
}
std::cout << b1->x << "\n";
std::cout << b2->x << "\n";