继承函数会读取父类或子类的数据成员吗?

时间:2014-10-20 14:04:18

标签: c++ inheritance virtual-functions

class A{
    int var;
public:
    virtual void foo(); // sets var
    void bar(); // reads var and displays value
};

class B : public A{
    int var;
public:
    void foo();
};

void A::bar(){
    printf("%d",var);
}

void B::foo(){
    var = 42;
}

void func(){
    B myObj;
    myObj.foo();
    myObj.bar();
}

class A2{
    virtual void foo(); // sets var
public:
    int var;
    void bar(); // read var and displays value
};

class B2 : public A2{
public:
    void foo();
};
  1. foo致电func后,foo会设置A::var还是B::var
  2. bar中的func来电barA::varB::var
  3. 如果不会创建var的实例,是否需要在A中将A声明为数据成员?
  4. 类声明A2B2是否与AB的效果相同?

4 个答案:

答案 0 :(得分:2)

关于1.和2.由于foo不可见(并且A::foo没有身体),因此出现错误:

class B : public A{
    int var;
    void foo();
};

无论如何,因为你没有通过指针/引用来调用它

void func(){
  B myObj;
  myObj.foo(); // No polymorphic behavior here, B::foo is called
  myObj.bar(); // the same, but A::bar is called since B hasn't one
}

关于3.和4.如果base和derived类都有一个具有相同名称的变量,派生的' s隐藏基类的名称,并且通过派生对象的每次访问都将导致派生的正在设置/调用(除非明确地执行base::var)。如果只有一个人拥有它,它就会很好,并且它们都会调用相同的版本(前提是它可见/可访问)。在上面的示例中:

void A::bar(){
   std::cout << var; // This will output an uninitialized A::var!
}

void B::foo(){
   var = 42; // B's var hides A's var so this only sets the derived one's
}

修改:在A2B2的情况下,A2::var只有一个实例,即使是派生类,每次访问它都会引用基础一,例如

class A2{
    virtual void foo() = 0;
public:
    int var;
    void bar() {
        std::cout << var; // Will correctly output 42
    }
};

class B2 : public A2{
public:
    void foo() {
        var = 42; // Sets the common A2::var variable
    };
};

void func2(){
    B2 myObj;
    myObj.foo();
    myObj.bar();
}

看看并研究以下内容: Example

答案 1 :(得分:1)

修复了注释中提到的私有问题后,还提供了A :: foo的实现,以避免&#34; undefined vtable&#34;错误,然后你会看到你正在调用B :: foo,它只留下A :: var,但是bar打印出A :: var。

在派生类中使用相同的变量名称相当愚蠢,但我会考虑到我未来的混淆要求。

A2和B2看起来不那么超现实。

答案 2 :(得分:1)

  

在func中调用foo后,foo会设置A :: var或B :: var?

foo将设置B :: var

  

在func中调用bar会禁止读取A :: var或B :: var?

func()中的

栏将返回A :: var,它将为零或未定义

  

如果没有A的实例,是否需要将var声明为A中的数据成员   会被创造出来吗?

是的,因为它是返回变量的void A :: bar()。

  

类声明A2和B2是否与A和A具有相同的效果   乙

不,A2 :: bar和B2 :: bar将返回相同的var(42)。

答案 3 :(得分:0)

  
      
  1. 在func中调用foo后,foo会设置A :: var或B :: var?
  2.   

foo()是虚拟的,myObj的动态(实际上是静态)类型是B,因此调用它B::foo(),设置{{1} }}

请注意,在这种情况下,B::var无效,因为您没有使用多态性。

  
      
  1. 在func中调用bar会禁止读取A :: var或B :: var?
  2.   

它会显示virtual

  
      
  1. 如果不创建A的实例,是否需要将var声明为A中的数据成员?
  2.   

您需要让我认为A::var虚拟,或者A::bar()在某个时刻调用B::foo()来设置基本成员变量。

  
      
  1. 类声明A2和B2是否与A和B的效果相同?
  2.   

您希望他们以何种方式与众不同?