多态性与引用成员变量

时间:2017-01-19 20:38:28

标签: c++ reference polymorphism pass-by-reference

有人可以告诉我下面的程序有什么问题吗?我在类中使用引用成员变量进行多态。我期待第二个cout说“derived2”,但它说“base”;

#include <iostream>

// Example program
#include <iostream>
#include <string>
class base
{
public:
    virtual void print(){ std::cout<<"base"<<std::endl;}
};
class derived: public base
{
public:
    virtual void print(){ std::cout<<"derived"<<std::endl;}
};

class derived2: public base
{
    virtual void print(){ std::cout<<"derived2"<<std::endl;}
};

class foo
{
public:
    base & bar;
    base boo;
    derived foobar;
    derived2 foobar2;
    foo(): bar(boo){}
    void newfoo(base & newfoo){ bar = newfoo; bar.print();}
};
int main()
{
  foo test;
  test.bar.print();
  test.newfoo(test.foobar2);
}

输出:     基础     基

4 个答案:

答案 0 :(得分:2)

如其他人所述,您无法重新分配参考文献 每当您执行bar = newfoo之类的操作时,您都不会重置参考。相反,您使用operator=作为参数调用bar newfoo 因此,在您的情况下,您正在切割您的对象,并(让我说)在base中复制其bar部分。

标准模板库中存在一种可以重新分配的类似参考工具,它名为std::reference_wrapper
它遵循一个基于您的代码的示例,该代码使用它并具有预期的行为:

#include<functional>
#include <iostream>
#include <string>

class base
{
public:
    virtual void print() { std::cout<<"base"<<std::endl;}
};
class derived: public base
{
public:
    virtual void print(){ std::cout<<"derived"<<std::endl;}
};

class derived2: public base
{
    virtual void print(){ std::cout<<"derived2"<<std::endl;}
};

class foo
{
public:
    std::reference_wrapper<base> bar;
    base boo;
    derived foobar;
    derived2 foobar2;
    foo(): bar(boo){}
    void newfoo(base & newfoo){ bar = newfoo; bar.get().print();}
};
int main()
{
  foo test;
  test.bar.get().print();
  test.newfoo(test.foobar2);
}

在这种情况下,operator=实际重新绑定对给定对象的引用。无论如何,正如您所看到的,在这种情况下,您必须调用get来访问基础引用。

注意:抛开上面的示例,您的代码不是std::reference_wrapper的典型用例。
我只是为了完整而提到它。

答案 1 :(得分:1)

您无法“重新分配”参考。当赋值运算符与引用一起使用时,它会分配基础值。

因此,bar = newfoo;只是将foo类型的base分配给foobar,并在此过程中对其进行切片。

如果您使用指针替换引用,则可能会有不同的行为,可以重新分配。

答案 2 :(得分:0)

bar是对boo的引用,boo的类型为base,无论您分配给它。

分配只能更改变量值,而不能更改其类型。

答案 3 :(得分:0)

多态性不适用于参考文献。试试这个:

#include <iostream>

// Example program
#include <iostream>
#include <string>
class base
{
public:
   virtual void print(){ std::cout << "base" << std::endl; }
};
class derived : public base
{
public:
   virtual void print(){ std::cout << "derived" << std::endl; }
};

class derived2 : public base
{
   virtual void print(){ std::cout << "derived2" << std::endl; }
};

class foo
{
public:
   base* bar; 
   foo(): bar(0) {}
   void newfoo(base* newfoo){ bar = newfoo; bar->print(); }
};

int main() {
   foo test;
   test.newfoo(new derived2);
}