1.面向對象指的是繼承,封裝,多態。
繼承主要關注類的構造,賦值,析構。
以下對多態,封裝進行補充說明。
2、多態
2.1.定義
a.賦值
派生類的指針,可以賦值給基類的指針。
派送類的對象,可以賦值給基類的引用。
b.調用
通過基類指針調用基類虛函數時,若派生類提供了派生實現,則調用派生類版本。
通過基類引用調用基類虛函數時,若派送類提供了派送實現,則調用派生類版本。
2.2.最佳實踐
基類的析構函數應該定義成虛函數。
#include <iostream>class Base
{
public:Base() {}virtual void fun(){printf("B_fun()\n");}virtual ~Base(){printf("~Base()\n");}protected:int m_pro;private:int m_pri;
};class A : public Base
{
public:A() : Base() {}void fun(){printf("A_fun()\n");}~A(){printf("~A()\n");}
};int main()
{A *pA = new A();Base *pB = pA;pB->fun();delete pB;A a;Base &b = a;b.fun();return 0;
}
2.3.注意點
多態針對類外部使用基類指針或基類引用調用基類虛函數時會發生。
多態針對基類內部調用虛函數,在隱式的this此時關聯到派生實例時也會發生。
#include <iostream>class Base
{
public:Base() {}virtual void fun(){printf("B_fun()\n");}void fun1(){printf("B_fun1()\n");fun();}virtual ~Base(){printf("~Base()\n");}protected:int m_pro;private:int m_pri;
};class A : public Base
{
public:A() : Base() {}void fun(){printf("A_fun()\n");}~A(){printf("~A()\n");}
};int main()
{A *pA = new A();Base *pB = pA;pB->fun1();delete pB;A a;Base &b = a;b.fun1();return 0;
}
3.封裝
3.1.訪問權限修飾符
a.c++支持的訪問權限修飾符有public,protect,private
。
b.在類型內部,針對類型自身所有成員(不含基類)具有全量(public,protect,private
)訪問權限。
c.在類型內部,針對類型基類,只能訪問基類的public,protect
修飾的成員。
c.在類型友元內部,具有等價于類型內部的訪問權限。故對類型自身成員有全量訪問權限,只能訪問基類的public,protect
修飾的成員。
d.在類型外部,針對類型自身成員,只對public成員具備訪問權限。針對基類成員,只對public繼承的基類的public成員具備訪問權限。
#include <iostream>class Base
{// 類的友元--全量訪問friend void friend_fun();
public:Base(int i, int j, int k) : m_pub(i), m_pro(j), m_pri(k) {}void fun(){// 類內部訪問--全量訪問printf("pub_%d,pro_%d,pri_%d\n", m_pub, m_pro, m_pri);}public:int m_pub;
protected:int m_pro;
private:int m_pri;
};class A1 : public Base
{friend void friend_funA1();public:A1(int i, int j, int k) : Base(i, j, k) {}void fun1(){// 公共繼承者的內部--只能訪問公共基類的public&protectprintf("pub_%d,pro_%d,pri_%d\n", m_pub, m_pro, 0);}
};// 保護繼承
class A2 : protected Base
{friend void friend_funA2();
public:A2(int i, int j, int k) : Base(i, j, k) {}void fun1(){// 保護繼承者的內部--只能訪問保護基類的public&protectprintf("pub_%d,pro_%d,pri_%d\n", m_pub, m_pro, 0);}
};// 私有繼承
class A3 : private Base
{friend void friend_funA3();public:A3(int i, int j, int k) : Base(i, j, k) {}void fun1(){// 私有繼承者的內部--只能訪問私有基類的public&protectprintf("pub_%d,pro_%d,pri_%d\n", m_pub, m_pro, 0);}
};void friend_fun()
{// 友元的內部--對類型自身成員全量訪問Base b(1, 2, 3);printf("pub_%d,pro_%d,pri_%d\n", b.m_pub, b.m_pro, b.m_pri);
}void friend_funA1()
{// 友元的內部--對基類,公共基類的public&protectA1 b(1, 2, 3);printf("pub_%d,pro_%d,pri_%d\n", b.m_pub, b.m_pro);
}void friend_funA2()
{// 友元的內部--對基類,保護基類的public&protectA2 b(1, 2, 3);printf("pub_%d,pro_%d,pri_%d\n", b.m_pub, b.m_pro);
}void friend_funA3()
{// 友元的內部----對基類,私有基類的public&protectA3 b(1, 2, 3);printf("pub_%d,pro_%d,pri_%d\n", b.m_pub, b.m_pro, 0);
}int main()
{Base b(11, 22, 33);// 類不相干的外部--針對類自身成員,只能訪問類自身的public成員。b.m_pub;A1 a1(2, 3, 4);// 類不相干的外部--針對類基類成員,只能訪問公共基類自身的public成員。printf("pub_%d,pro_%d,pri_%d\n", a1.m_pub, 0, 0);// 類不相干的外部--針對類基類成員,只能訪問公共基類自身的public成員。A2 a2(3, 4, 5);printf("pub_%d,pro_%d,pri_%d\n", 0, 0, 0);// 類不相干的外部--針對類基類成員,只能訪問公共基類自身的public成員。A3 a3(4, 5, 6);printf("pub_%d,pro_%d,pri_%d\n", 0, 0, 0);
}
理解繼承時,對基類的權限修飾。可以認為是指定基類成員被合并到派生類成員時,允許放入的權限區域。
對public繼承,允許被放入public,protect,private區域。所以,按基類成員一致權限放入。
對protect繼承,允許被放入protect,private區域。所以,基類public,protect成員放入protect區域;private成員放入private區域。
對private繼承,允許被放入private區域。所以,基類成員一致放入private區域。