我有一个来自B
的课程A
,其中有一个名为type
的成员我想从类B
的方法访问,但不是实际值我得到一个0
,但如果我在this
方法中将A
转换为B
,它会正常工作,如下所示:((A*)this)->type
所以它会给我实际值0
。有人可以解释一下吗?我写了一个我的实际类的简短版本来给出一个代码示例。
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
enum TYPE
{
T_INTEGER = 2,
T_FLOAT = 4
};
struct A
{
enum TYPE type;
A(enum TYPE);
A();
int print();
};
struct B : A
{
enum TYPE type;
B(enum TYPE);
};
struct Number : B
{
union
{
int intvalue;
float floatvalue;
};
Number(int);
int print();
};
A::A() { }
A::A(enum TYPE Type)
: type(Type)
{
}
B::B(enum TYPE kind) :
A(kind)
{
}
Number::Number(int v)
: B(T_INTEGER),
intvalue(v)
{
}
int Number::print()
{
printf("type = %d\n", type); // output: type = 0 (wrong)
printf("type = %d\n", ((A*)this)->type); // output type = 2 (correct) but why do I need cast?
switch(((A*)this)->type)
{
case T_INTEGER:
return printf("%d", intvalue);
case T_FLOAT:
return printf("%g", floatvalue);
default:
assert(0);
}
}
int main()
{
Number *n = new Number(2);
n->print();
delete n;
}
答案 0 :(得分:2)
您已声明成员变量
enum TYPE type;
这两个课程B
和 A
但您的B
构造函数从未使用该名称初始化其自己的变量 - 它只是将其传递给初始化A
A::type
构造函数
B::B(enum TYPE kind) :
A(kind)
{
}
因此,B
成员永远不会被初始化。目前尚不清楚为什么你在派生类B
中再添加了一个相同名称和类型的变量,但我的猜测是,你可能不打算这样做,而只是想在基础中使用这种类型的单个变量班A
当您在派生类和基类中具有相同变量名和类型的情况时,派生类成员将隐藏基类成员 - 这就是从type
方法访问Number::print()
的原因到B
成员而不是A
成员。显然,然后将this
投射到A*
会访问A::type
成员。
答案 1 :(得分:1)
您在type
和A
中声明了成员变量B
。但是B
从type
继承了成员变量A
。这意味着B
类型的每个对象都包含两个 type
变量:A::type
和B::type
。由于Number
源自B
,因此它同时包含A::type
和B::type
。当您在type
的成员函数中使用非限定名称Number
时,它会解析为B::type
,因为B
在继承层次结构上低于A
。该成员未由您的构造函数初始化;仅初始化A::type
。但是((A*)this)->type
是指A::type
。 (旁注:在这种情况下,请static_cast<A*>(this)
为(A*)this
。)
此处的解决方案可能是从type
的定义中删除B
的声明。 (但我不确定你要做什么。)
答案 2 :(得分:0)
您需要初始化Number变量类型,因为这是您要打印的内容。
Number::Number(int v)
: B(TYPE::T_INTEGER),
intvalue(v)
{
this->type = TYPE::T_INTEGER;
}
就像这样,初始化本地类型,因此它将打印2。
答案 3 :(得分:0)
您必须进行强制转换,因为结构A和B都具有完全相同名称和类型的属性。编译器还能如何为您提供正确的值?如果你没有施放,那么你得到了一个你从未初始化过的与B相关联的那个,所以只有运气不好才归零。它与在A类中声明/定义的那个完全分开。我的猜测是B中的变量隐藏A中的变量,而获取A中的变量的唯一方法是进行强制转换并明确告诉编译你想要的。摆脱B中的那个,因为你还没有设置它,它应该可以正常工作。