我在照着STL 源码刨析写 STL 的时候出现了一个编译错误. 当时的情况是我要用一个派生类的指针给一个基类指针的引用赋值, 类似于:
class Base {};
class Derived : public Base {};
Derived *d = new Derived();
Base *&b = d;
但是编译器报错, 错误信息类似于:
error: cannot bind non-const lvalue reference of type ‘Base*&’ to an rvalue of type ‘Base*’
在 C++ 中, 派生类的指针可以直接给基类指针赋值以实现多态的特性. 但是却不可以给基类指针的引用赋值. 这个报错当时令我很困惑. 经过查阅并分析报错信息, 该语句的执行过程应该是首先创建了一个类型为 Base*
的临时值, 用 d
来初始化, 再把这个临时值赋予变量 b
. 因为这个临时值是右值不能给左值赋值, 所有会有这个报错.
这个问题可以用两种方式解决.
第一种方式是通过常量引用可以指向右值实现的. 就是把变量 b
声明为常量指针, 即 Base * const &b = d
, 这样就解决了这个问题.
但是在我当时的代码中不能通过这个方法解决. 因为报错的函数是红黑树的一个迭代函数, 有可能改变 d
的值. 这样的解决方法会复制 d
的值, 使得函数内改变的局部值无法作用到外部的 d
上.
第二种方式是先把 d
做一个强制类型转换再赋值给 b
, 即 Base *&b = (Base*&)d
. 这样就可以在函数中通过修改 b
的值修改 d
.
下面是一个示例代码. 验证两种方法.
class Base {};
class Derived : public Base {};
Derived *pd = new Derived();
Base * const &pb1 = pd; // 方法 1
Base *&pb2 = (Base*&)pd; // 方法 2
cout << "addr of pd:\t" << &pd << endl;
cout << "addr of pb1:\t" << &pb1 << endl;
cout << "addr of pb2:\t" << &pb2 << endl;
编译没有报错, 运行得到下面的结果:
add of pd: 0x7ffcdec09978
add of pb1: 0x7ffcdec09980
add of pb2: 0x7ffcdec09978
说明方法 1 创建了一个新的指针, 而方法 2 绑定在原来的指针上.
标签:一次,错误,Derived,编译,Base,报错,pd,赋值,指针 From: https://www.cnblogs.com/TechThing/p/17522506.html