c++(1)

来源:互联网 发布:如何下载excel2007软件 编辑:程序博客网 时间:2024/05/22 03:17

重载的注意事项:

如果只有返回类型不同,参数相同(个数,类型,顺序都相同),这是不允许的.编译器的事情过关.

派生类成员名与基类成员名同名时:

覆盖:

  • 父子关系 成员(数据成员或函数成员)同名
  • 基类成员必须有virtual关键字,子类则可有可无
  • 参数与返回值必须与父类虚函数相同,否则不能覆盖而是隐藏
  • 基类虚函数被覆盖的同时,该虚函数的重载函数被隐藏.
隐藏:父子关系 成员(数据成员或函数成员)同名  --->隐藏notice:基类的虚函数也可以被隐藏;派生类与基类的返回值,参数完全一致时基类虚函数才会被覆盖(p501)

virtual成员被子类重写(覆盖),非virtual成员被隐藏。

在派生类中访问基类被隐藏的成员可以使用语法   基类名::成员名。

virtual在修饰函数的时候的限制:

  1. 普通函数不能是虚函数
  2. 静态成员函数(不属于任何对象,与类同生共死)不能是虚函数
  3. 内联函数不能是虚函数;如果用virtual修饰内联函数,计算机就会忽略inline关键字,使它变成一个纯粹的虚函数
  4. 不能用virtual关键字修饰构造函数
  5. 如果在函数声明后加上=0,则就成为了纯虚函数,e:public void virtual add(p1,p2)=0;

//例子....注意访问修饰符,基类的private属性在派生类中是无法直接(可以在派生类中调用基类的非私有方法访问)访问的。。。

  1. #include <iostream>
  2. #include <stdlib.h>
  3. #include <string>
  4. using namespace std;
  5. /**
  6.  * 定义人类: Person
  7.  * 数据成员: m_strName
  8.  * 成员函数: attack()
  9.  */
  10. class Person
  11. {
  12. public:
  13.     string m_strName;
  14.     void attack()
  15.     {
  16.         cout << "attack" << endl;
  17.     }
  18. };
  19. /**
  20.  * 定义士兵类: Soldier
  21.  * 士兵类公有继承人类
  22.  * 数据成员: m_strName
  23.  * 成员函数: attack()
  24.  */
  25. class Soldier:public Person
  26. {
  27. public:
  28.     string m_strName;
  29.     void attack()
  30.     {
  31.         cout << "fire!!!" << endl;
  32.     }
  33. };
  34. int main(void)
  35. {
  36.     // 实例士兵对象
  37.     Soldier soldier;
  38.     // 向士兵属性赋值"tomato"
  39.     soldier.m_strName = "tomato";
  40.     // 通过士兵对象向人类属性赋值"Jim"
  41.     soldier.Person::m_strName= "Jim";
  42.     // 打印士兵对象的属性值
  43.     cout << soldier.m_strName << endl;
  44.     // 通过士兵对象打印人类属性值
  45.     cout << soldier.Person::m_strName << endl;
  46.     // 调用士兵对象方法
  47.     soldier.attack();
  48.     // 通过士兵对象调用人类方法
  49.     soldier.Person::attack();
  50.     return 0;
  51. }


常成员函数含义:不能修改对象成员值的函数。如果企图用常成员函数修改值,
如某书:
1.常成员函数不能更新对象的数据成员
2.当一个对象被声明为常对象,则不能通过该对象调用该类中的非const成员函数;在C++中,常对象只能调用常成员函数,常成员函数不能调用非常成员函数

//原因----例子
class Coordinate{
    public:
        Coordinate(int x,int y);
         void changeX() const;
        void chaangeX();//const也构成重载
    private:
      int x;
      int y;
};
//错误写法
Coordinate::changeX() const{
  y=10;//error
}
该函数的实现等价于(系统是这么做的):
Coordinate::changeX(const Coordinate *this) const{
    this->y=10;
}
常成员函数相当于在this指针参数前面加了一个const限定,而默认的情况下const type *是不能转换为type *的但type *可以转换为const type *。所以,常对像就只能调用常成员函数,而非常对象就都可以调用


 C++中继承时构造函数的调用顺序:1,如果继承虚基类,先调用虚基类的构造函数,如果有多个虚基类,按顺序调用。2,如果继承基类,调用基类的构造函数;如果有多个基类,按顺序调用。3,如果类中定义了成员对象,调用成员对象的构造函数;如果有多个成员对象,则按成员对象定义的顺序调用;4,调用自身的构造函数;析构函数的调用顺序与此相反。 

在内存的角度看is-a


is-a:
(1)当一个子类的对象去初始化或者对一个父类的对象赋值时,本质上就是把子类从父类所继承下的数据成员赋值给父类对应数据成员,此时子类对象的其他数据成员就会丢失<br>
(2)若是父类的一个对象指针指向一个子类的对象,则访问也只能访问到从父类继承下来的数据成员。(本质上都是在访问自己(即子类)数据成员所在的内存空间,人为概念上区分了,但是硬件本质上操作的还是同一块内存区域)
虚函数原理:

抽象类:含有纯虚函数(放个标识,让子类去实现)的类称作为抽象类
  1. 抽象类无法实例化对象
  2. 抽象类的派生类只有把父类的所有纯虚函数都实现后才能去实例化对象,否则派生类仍然是一个抽象类
接口类:仅含有纯虚函数的类称作为接口类
  1. 没有数据成员
  2. 只有成员函数
  3. 成员函数都为虚函数

0 0
原创粉丝点击