您的位置:首页 > 其它

继承

2016-03-19 13:52 429 查看
[b]一.子类不继承父类构造函数,析构函数,默认私有继承或protected[/b]

[b]二.using声明可在子类把父类成员改为私有[/b]

class B
{
public:
void set(){}
};

class C: public B
{
private:
using B::set;
};


[b]三.派生类成员与父类成员名字相同,会发生名字隐藏[/b]

#include <iostream>
#include <string>
using namespace std;

class B
{
public:
void h(float x){}
};

class C: public B
{
public:
void h(string s){}
};

int main()
{
C c;
c.h("abc");//ok
c.h(1.7);//error
c.B::h(1.7);//ok
return 0;
}


[b]四.派生类可对从基类继承来的保护成员进行访问,也就是说保护成员在派生类中是可见的[/b]

[b]派生类不能访问一个基类对象的保护乘员,因为基类对象属于基类,不属于派生类[/b]

[b][b]派生类中的派生类可访问基类的保护乘员,因为派生类对象属于派生类[/b][/b]

#include <iostream>
#include <string>
using namespace std;

class B
{
protected:
int get_W() const { return 0; }
};

class C: public B
{
public:
int get_V()const { return get_W(); }
void base_W(const B &b) const { cout << b.get_W() << endl; }//error
void p(C &c)const { cout << c.get_W() << endl; } // OK

};

int main()
{
C c;
c.getW(); //error, protected
return 0;
}


应避免将数据成员设置成protected,而应采用私有或者相应保护类型访问函数

[b]五.创建派生类时,父类默构自动调用。父类若有带参构造,则必须有自定义默构,除非显示调用基类带参构造。[/b]

#include <iostream>
#include <string>
using namespace std;

class Base
{
public:
Base(int m, int n)
{
x = m;
y = n;
}
private:
int x, y;
};

class Derived: public Base
{
public:
Derived(int m, int n, int k):Base(m, n)
{
z = k;
}
private:
int z;
};

int main()
{
Derived d(1, 2, 3);
return 0;
}


#include <iostream>
#include <string>
using namespace std;

class Base
{
public:
Base(int m, int n)
{
x = m;
y = n;
}
private:
int x, y;
};

class Derived: public Base
{
public:
Derived(int k)
{
z = k;
}
private:
int z;
};

int main()
{
Derived d(3);//error, Base没有合适的默认构造函数可用
return 0;
}


1.最先调用基类的构造函数,对基类数据成员初始化顺序取决于被继承时的说明顺序;

2.再调用数据成员是类对象的构造函数,顺序按类中定义的先后顺序;

3.最后执行派生类构造函数;

4.析构函数的调用与构造函数正好相反,由于每个类至多只有一个析构函数,调用时不会产生二义性。

[b]六.多重继承机制下的命名冲突[/b]

#include <iostream>
#include <string>
using namespace std;

class A
{
public:
void f();
};

class B
{
public:
void f();
void g();
};

class C: public A, public B
{
public:
void h();
void g();
};

int main()
{
C c;
c.g();//c中g(),B中被重写
c.f();//error,无法确定,若B:public A则c.f()不会产生二义性

c.B::g();
c.A::f();
c.B::f();
return 0;
}


#include <iostream>
#include <string>
using namespace std;

class B
{
public:
int b;
};

class B1:public B
{};

class B2:public B
{};

class C: public B1, public B2
{};

int main()
{
C c;
c.b;//error,b不明确
c.B::b;//B不明确,在VS2015中默认为B1中的B的b
/*
C->B1->B->b
->B2->B->b
基类对象B在派生类C中存储2份
*/
return 0;
}


在多条继承路径上有一个公共基类,希望只存储一个公共基类时,可利用虚基类。

#include <iostream>
#include <string>
using namespace std;

class B
{
public:
int b;
};

class B1: virtual public B
{
public:
int b1;
};

class B2: virtual public B
{
public:
int b2;
};

class C: public B1, public B2
{
public:
int c;
};

int main()
{
C c;
c.B1::b = 1;
c.B2::b = 2;
cout << c.B1::b << endl; // 2 没有同时2个virtual则为1,存储了2个B
cout << c.B2::b << endl; // 2
/*
B1
C->  ->B
B2
C中b值只存储了一份
*/
return 0;
}


虚基类的构造函数先于非虚基类执行

虚基类由最派生类(最后一个派生类)调用构造函数初始化

#include <iostream>
#include <string>
using namespace std;

class A
{
public:
A()
{
cout << "A" << endl;
}
~A()
{
cout << "~A" << endl;
}
};

class B: public A
{
public:
B()
{
cout << "B" << endl;
}
~B()
{
cout << "~B" << endl;
}
int b;
};

class B3
{
public:
B3()
{
cout << "B3" << endl;
}
~B3()
{
cout << "~B3" << endl;
}
int b3;
};

class B1: public B3, virtual public B
{
public:
B1()
{
cout << "B1" << endl;
}
~B1()
{
cout << "~B1" << endl;
}
int b1;
};

class B2: virtual public B
{
public:
B2()
{
cout << "B2" << endl;
}
~B2()
{
cout << "~B2" << endl;
}
int b2;
};

class D
{
public:
D()
{
cout << "D" << endl;
}
~D()
{
cout << "~D" << endl;
}
int c;
};

class E
{
public:
E()
{
cout << "E" << endl;
}
~E()
{
cout << "~E" << endl;
}
int c;
};

class C: public B1, public B2
{
public:
C()
{
cout << "C" << endl;
}
~C()
{
cout << "~C" << endl;
}
int c;
D d; E e;
};

int main()
{
C c;
return 0;
}




[b]七.继承方式[/b]

1.公有继承:基类成员公有和保护在派生类中保持原有访问属性,私有成员仍为基类私有;

2.私有继承:基类公有和保护在派生类中成私有成员,私有成员仍为基类私有;

3.受保护继承:基类公有和保护在派生类中成保护成员,私有成员仍为基类私有。保护成员:不能被外界访问,但可被派生类成员访问

[b]八.对基类对象操作的函数,可以对子类的对象进行操作,不可逆[/b]

1.派生类对象可以赋值给基类:Base b; Derived d; b = d;

2.Derived d; Base &b = d;初始化基类引用

3.子类地址赋值给基类指针Derived d; Base *b = &d;

必须是public继承关系,protected和private不成立
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: