命名白白c++ 基类和派生类的转换

2014-11-24 02:37:41 · 作者: · 浏览: 2

派生类转换为基类
我们先明确几个概念,如果我理解的不对希望能有大神指出错误。

第一是,无论哪种继承方式,子类拥有父类的所有成员变量和成员函数,只是访问权的问题。举个例子


[cpp] view plaincopyprint
#include
using namespace std;

class A
{
public:
int i;
};

class B:public A
{
public:
int i;
};

int main()
{
B b;
b.i = 10;
A &a = b;
cout< }

#include
using namespace std;

class A
{
public:
int i;
};

class B:public A
{
public:
int i;
};

int main()
{
B b;
b.i = 10;
A &a = b;
cout< }大家觉得最后输出的结果是多少?

不是10.而是一个随机值

我的电脑是1629101750。

这说明什么问题呢,B中有两个i,一个是父类的i,一个是自己的i.

但是一般程序设计的人绝对不会这么设计的,因为一般名字一样只要父类有,子类继承就可以了。

但是考试的人,就会这么出题了,这就是为什么大家写了那么多年程序,很多面试题还是没有见过,还是不会,第一是我们基础不牢固,第二是这些地方的实用性其实不是那么大,可能永远不会用到。 不过如果为了提高自己,主要是为了防止出差,很多细节还是需要研究研究,多写写代码,来验证自己的思想是不是正确。


那么派生类转换为基类怎么理解呢?

按照c++ primer 中的说法有两种形式,一种就是给基类赋值,一种是转换为基类的引用或者指针。派生类对象自身并没有变成基类对象。

这两种方式有一些细微的区别,很多时候最好使用常引用最为函数的入参,为什么呢?因为引用少了赋值的操作,效率上面会高一些。

可以查看我写的c++赋值的几种方式, , 直接赋值应该是c语言中保留下来的,在c++中它的作用似乎就不大了,尤其对类和对象的。

大家看看下面的例子


[cpp]
#include
using namespace std;


class A
{
public:
A();
A(A &a);
A(int i);
void set(A a);
int getI();
virtual void print();
private:
int i;
};
void A::print()
{
cout<<"A print"< }


A::A()
{
}
A::A(A& a)
{
i = a.i;
}
A::A(int i)
{
this->i = i;
}
int A::getI()
{
return i;
}
void A::set(A a)
{
i = a.i;
}




class B: public A
{
public:
B(int i);
virtual void print();


private:
int k;
int i;
};


void B::print()
{
cout<<"B print"< }




B::B(int i)
{
i = 5;
}




int main()
{
A a(10);
B b(5);

A a1(a);
A a2(b);


cout< cout<
A a_next(20);
B b_next(15);
a1.set(a_next);
a2.set(b_next);

cout< cout<
A &a3(b);
a1.print();
a2.print();
a3.print();


}

#include
using namespace std;


class A
{
public:
A();
A(A &a);
A(int i);
void set(A a);
int getI();
virtual void print();
private:
int i;
};
void A::print()
{
cout<<"A print"< }


A::A()
{
}
A::A(A& a)
{
i = a.i;
}
A::A(int i)
{
this->i = i;
}
int A::getI()
{
return i;
}
void A::set(A a)
{
i = a.i;
}


class B: public A
{
public:
B(int i);
virtual void print();


private:
int k;
int i;
};


void B::print()
{
cout<<"B print"< }


B::B(int i)
{
i = 5;
}


int main()
{
A a(10);
B b(5);

A a1(a);
A a2(b);


cout< cout<
A a_next(20);
B b_next(15);
a1.set(a_next);
a2.set(b_next);

cout< cout<
A &a3(b);
a1.print();
a2.print();
a3.print();


}

觉得输出的结果是什么呢?

我这里的答案是:

10
2293028
20
1628665296
A print
A print
B print


为什么呢?

子类会调用父类的默认构造函数,根据上面的内容,上题中子类中包含父类的所有元素和方法,但是父类中的默认构造函数没有初始化自己的i,这样i就是个随机值。

子类无论是给父类赋值,还是转换为父类的构造函数,父类中的i永远都没有被初始化,所以结果就是上面的内容。


后面的print函数,我们又回顾了一下虚函数的用法,虚函数只对引用和指针有作用。切记!


基类转换为派生类
这个不可以,这个转换关系不存在。