具有引用成员变量的多态性
polymorphism with reference member variable
有人能告诉我下面的程序有什么问题吗?我在 class 中使用引用成员变量来实现多态性。我期待第二个 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);
}
输出:
根据
基地
bar
是对 boo
的引用,而 boo
是 base
类型,无论您分配给它什么。
赋值只能改变一个变量的值,不能改变它的类型。
您不能'reassign'参考。当赋值运算符与引用一起使用时,它会分配基础值。
因此,bar = newfoo;
只是将base
类型的foo
分配给foobar
,并在过程中将其切片。
如果将引用替换为指针,可能会有不同的行为,指针可以是 re-assigned。
多态性不适用于引用。试试这个:
#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);
}
正如其他人所提到的,您不能重新分配参考。
每当您执行 bar = newfoo
之类的操作时,您都不会重置引用。相反,您使用 newfoo
作为参数为 bar
调用 operator=
。
因此,在您的情况下,您正在 切片 您的对象并(让我说)将其 base
部分复制到 bar
.
标准模板库中有一种reference-like可以重新分配的工具,它叫做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
.
的典型用例
我提到它只是为了完整起见。
有人能告诉我下面的程序有什么问题吗?我在 class 中使用引用成员变量来实现多态性。我期待第二个 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);
}
输出: 根据 基地
bar
是对 boo
的引用,而 boo
是 base
类型,无论您分配给它什么。
赋值只能改变一个变量的值,不能改变它的类型。
您不能'reassign'参考。当赋值运算符与引用一起使用时,它会分配基础值。
因此,bar = newfoo;
只是将base
类型的foo
分配给foobar
,并在过程中将其切片。
如果将引用替换为指针,可能会有不同的行为,指针可以是 re-assigned。
多态性不适用于引用。试试这个:
#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);
}
正如其他人所提到的,您不能重新分配参考。
每当您执行 bar = newfoo
之类的操作时,您都不会重置引用。相反,您使用 newfoo
作为参数为 bar
调用 operator=
。
因此,在您的情况下,您正在 切片 您的对象并(让我说)将其 base
部分复制到 bar
.
标准模板库中有一种reference-like可以重新分配的工具,它叫做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
.
的典型用例
我提到它只是为了完整起见。