Skip to content

Latest commit

 

History

History
212 lines (167 loc) · 5.73 KB

面向对象.md

File metadata and controls

212 lines (167 loc) · 5.73 KB

面向对象

  • 基类都有虚析构函数
class Quote
{
public:
	// 默认构造函数,以此方式定义默认构造函数是希望既有默认构造函数,还有其他形式的构造函数
	Quote() = default;
	// 带参数的构造函数
	Quote(const std::string &book,double sales_price):
		bookNo(book), price(sales_price){ }
	//成员函数
	std::string isbn() const { return bookNo; }
	// 虚函数(允许在子类中重写方法)
	virtual double net_price(std::size_t n) const
	{
		return n * price;
	}
	// 虚析构函数(基类通常需要定义)
	virtual ~Quote() = default;
private:
	std::string bookNo;
protected:
	double price = 0.0;
};
  • 派生类不总是覆盖基类的虚函数

  • 在一个对象中,继承自基类的部分和派生类自定义的部分不一定是连续存储的

  • Quote item; // 基类对象
    Bulk_quote bulk; // 派生类对象
    Quote *p = &item; // p指向基类Quote对象
    p = &bulk; // p指向派生类bulk中的Quote部分
    Quote &r = bulk; // r绑定到bulk的Quote部分
  • 派生类可以访问基类的公有成员和受保护成员

  • 静态成员只存在唯一的定义

  • 成员函数可以在类内定义和生明,也可以在类内声明,类外定义

    class Base
    {
        public:
        void f(const Base&);
    };
    // 在类内声明成员函数, 类外定义 
    void Base::f(const Base& deli)
    {
        .....;
    };
  • 一个派生类的函数如果覆盖了某个继承而来的虚函数,则它的形参类型必须与被它覆盖的基类函数完全一致;返回类型也必须匹配

  • 可以把某个函数指定为final,则任何操作都不能覆盖该函数

    void f(int) const final;
  • =0声明一个纯虚函数;含有纯虚函数的类是抽象基类;不能创建抽象基类的对象

  • 派生类的成员友元只能通过派生类对象来访问基类的受保护对象

  • 友元关系不能传递,也不能继承

    class Base
    {
        friend class Pal; // 声明友元类
        protected:
        int prot_mem;
    };
  • 使用using可以改变派生类的成员的访问级别

    class Base
    {
        public:
        std::size_t size() const { return n; }
        protected:
        std::size_t n;
    };
    class Pal : private Base // Pal私有继承自Base,则继承来的成员是Pal的私有成员,使用using改变成员的访问等级
    {
        public:
        using Base::size;
        protected:
        using Base::n;
    };
  • 默认情况下,使用class关键字定义的派生类是私有继承;使用struct关键字定义的派生类是公有继承

    class Base{...};
    class D1 : Base{...}; //私有继承
    struct D2 : Base{...}; //公有继承
  • 派生类的成员隐藏同名的基类成员

    struct Base
    {
        Base() : mem(0){ } //用0初始化 mem
        protected:
        int mem;
    };
    struct Derived : Base{
        Derived(int i): mem(i){ } // 用i初始化 i
        int get_mem() {return mem;}
        // 可以使用作用域运算符来访问隐藏的基类成员
        int get_base_mem() {return Base::mem;}
        protected:
        int mem;
    }
  • 类对象在被创建时,就会调用构造函数;被销毁时调用析构函数

  • 当一个继承自基类的对象被创建时,先调用基类的构造函数,在调用自己的构造函数,当该对象被销毁时,先调用自己的析构函数,再调用基类的析构函数

友元

  • 目的:让一个函数或者一个类,访问另一个类中的私有成员

  • class Student
    {
         // 在类内将 外部函数声明为该类的友元
    	friend void friend_Student(Student* s);
    public:
    	int m_age;
    	Student()
    	{
    		m_age = 20;
    		m_name = "青春";
    	}
    private:
    	std::string m_name;
    };
    
    void friend_Student(Student* s)
    {
    	
    	std::cout <<"在类外访问公有成员"<< s->m_age << std::endl;
    	std::cout <<"在类外访问私有成员"<< s->m_name << std::endl;
    }
    int main()
    {
    	Student s;
    	friend_Student(&s);
    	return 0;
    }

匿名对象

  • 当前行被执行完成后,立即释放

  • class Base
    {
     public:
     	Base()
        {
            std::cout<<"hello"<<std::endl;
        }
    }
    
    Base(); // 创建一个匿名对象,当前行执行完后立即释放

继承

  • 父类的私有成员不管以什么方式继承都不可以访问
  • 公有继承不改变父类中的访问权限
    • 公有继承下类内可以访问父类的protected成员
  • 保护继承下,父类的public成员在子类中变为protected,子类外部无法访问
  • 保护权限类外不可以访问
  • 如果子类中有跟父类同名的成员函数,则父类中与子类成员函数同名的成员函数会被隐藏
  • 虚继承virtual可以解决菱形继承问题(虚继承)
  • 允许父类与子类之间的转换,父类的引用或指针可以直接指向子类对象
  • 当子类重写父类的虚函数,子类中的虚函数表内部,会替换成子类的虚函数地址,当父类的指针或者引用指向子类对象时,发生多态

纯虚函数和抽象类

  • 纯虚函数语法:virtual 返回值类型 函数名(参数列表)= 0;
  • 当类中有了纯虚函数,这个类被称为抽象类
  • 抽象类无法实例化对象
  • 子类必须重写抽象类中的纯虚函数,否则也属于抽象类

虚析构和纯虚析构

  • 使用多态时,如果子类中有属性开辟到堆区,那么父类指针在释放时无法调用到子类的析构代码;解决该问题的方式是将父类的析构函数改为虚析构或者纯虚析构