您的位置:首页 > 编程语言 > C语言/C++

C++ Primer 学习笔记(9): 基类和派生类的转换

2010-03-24 20:14 246 查看
1、派生类到基类的转换


如果有一个派生类型的对象,则可以使用它的地址对基类类型的指针进行赋值或初始化。同样,可以使用派生类型的引用或对象初始化积累类型的引用。严格说来,对对象没有类似转换。编译器不会自动将派生类型对象转换成基类类型对象。

1.1 引用转换不同于转换对象


将派生类型的对象传给希望接受基类引用的函数时,引用直接绑定到该对象,虽然看起来是在传递对象。转换不会改变派生类型对象,该对象仍然是派生类型对象。

当将派生类型对象传给希望接受基类类型对象的函数时,情况完全不同。这时该派生类对象的基类部分被复制到形参。

1.2 用派生类对象对基类对象进行初始化或赋值


用派生类对象对基类对象赋值有两种情况

(1) 基类显式定义了将派生类型对象赋值或复制给基类对象的函数,即构造函数或赋值运算符来实现,这时根据用户定义的动作来进行转换。

(2)未定义上述操作,则派生类的非基类成员被切掉,只将基类部分赋值给基类对象。

1.3 派生类到基类转换的可访问性



关于这个问题,在C++ primer 4 中文版上翻译的很恶心,如下:

如果是public继承,则用户代码和后代码类都可以使用派生类到基类的转换。如果类是使用private或protected继承派生的,则用户代码不能将派生类型对象转换为基类对象。如果是private继承,则从private继承类派生的类不能转换为基类。如果是protected继承,则后续派生类的成员可以转换为基类类型。
对比英文版:
If the inheritance is public, then both user code and
member functions of subsequently derived classes may use
the derived-to-base conversion. If a class is derived
using private or protected inheritance, then user code
may not convert an object of derived type to a base type
object. If the inheritance is private, then classes
derived from the privately inherited class may not
convert to the base class. If the inheritance is
protected, then the members of subsequently derived
classes may convert to the base type.
另外有一个Tips:
To determine whether the conversion to base is accessible, consider whether a public member of the base class would be accessible. If so, the conversion is accessible; otherwise, it is not.
中文版上是:
要确定到基类的转换是否可访问,可以考虑基类的public成员是否可访问,如果可以,转换是可访问的,否则,不可访问


这一段我到现在没弄明白,写了一段代码验证:

#include"iostream"
using namespace std;
class c00
{
public:
void print()
{
cout<<"c00::print"<<endl;
}
private:
int c00a;
};
class c10 : public c00
{
private:
int c10a;
public:
void f(const c00 & c) //1 ok
{ }
};
class c11 : protected c00
{
private:
int c11a;
public: void f(const c00 & c) //5 ok
{ }
};
class c12 : private c00
{
private:
int c12a;
public: void f(const c00 & c) //5 ok
{ }
};
class c21 : public c11
{
private:
int c21a;
public:
void f(const c00 & c) //4 ok
{
}
};
class c22 : public c12
{
private:
int c22a;

public:
c00 test;          //error,连定义c00对象都不可以
void f(const c00 & c) //3 error
{ }
};
void f(const c00 & c)
{ }
int main()
{
c10 t10;
c21 t21;
c12 t22;
f(t10); //1 ok
//  f(t21); //2 error
// f(t22); //2 error
}


从中可以发现,假设类层次如下

base;

son:private base;

grandson: xxx son;

则在grandson中甚至都不能定义base类型的对象,自然也就不存在什么访问权限的问题了,而如果son的继承方式是son:protected base,则没有问题,但是son仍然不能传递给一个base类型的引用或指针

上面的代码稍作改动就可以通过:

class c22 : public c12
{
private:
int c22a;

public:
::c00 test;      //现在ok了
void f(const ::c00 & c) //ok!!!
{ }
};


2、基类到派生类的转换


基类到派生类的自动转换是不存在的,将基类对象赋值给派生类会出现错误。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: