为什么我需要一个强制类型来访问基类的实际值?

时间:2014-03-07 19:48:19

标签: c++ enums base-class

我有一个来自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;
}

4 个答案:

答案 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)

您在typeA中声明了成员变量B。但是Btype继承了成员变量A。这意味着B类型的每个对象都包含两个 type变量:A::typeB::type。由于Number源自B,因此它同时包含A::typeB::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中的那个,因为你还没有设置它,它应该可以正常工作。