• C++学习笔记-类相关问题总结


    1、默认构造函数

    默认构造函数要么没有参数,要么所有参数都有默认值。如果没有定义任何构造函数,编译器将自定义默认构造函数。

    自动生成的默认的构造函数的作用:

    (1)使可以创建对象

    (2)调用基类的默认构造函数以及调用本身是对象的成员所属类的默认构造函数。

    如果派生类构造函数的成员初始化列表中没有显示地调用基类的构造函数,则编译器将使用基类的默认构造函数构造派生类对象的基类部分。

    2、复制构造函数

    Class_name(const Class_name &);

    在下述情况下,将会使用赋值构造函数:

    (1)将新的对象初始化为一个同类的对象。

    (2)按值将对象传递给函数

    (4)函数按值返回对象

    (5)编译器生成临时对象

    如果类没有显示定义复制构造函数,编译器将提供一个默认的复制构造函数,逐个复制非静态成员函数(浅复制)。

    当类中包含了使用new初始化的指针成员时,默认复制构造函数是不合适的,需要显示定义复制构造函数。

    3、赋值操作符

    当已有的对象赋给另一个对象时,将使用重载的赋值操作符。

    原型如下:

    Class_name & Class_name::operator=(const Class_name &);

    赋值操作符的隐式实现也是对成员逐个进行复制。当默认赋值操作符不合适的时候,就应当显式定义赋值操作符。

    4、析构函数

    析构函数一般要定义为虚函数,除非该类不做基类。

    使用虚拟的析构函数可以确保按正确的顺序调用析构函数。

    5、按值传递对象与传递引用

    传递对象的引用的原因:

    (1)提高效率

    按值传递对象涉及到生成临时拷贝(调用复制构造函数),然后调用析构函数。

    (2)多态

    基类的引用可以应用派生类的对象

    6、返回对象和返回引用

    返回引用的原因还是在于提高效率。

    但不能总返回引用:

    (1)不能返回在函数中创建的临时对象的引用

    (2)如果函数返回的是通过引用或指针传递给它的对象,则应返回引用。

    (3)如果函数返回在函数中创建的临时对象,则不应该返回引用。

    7、不能被继承的函数

    构造函数

    创建派生类的对象时,必须调用派生类的构造函数。派生类可以通过使用成员初始化列表来调用基类的构造函数。

    class Base
    {
    public:
    	Base(int a):number(a)
    	{
    
    	}
    	int GetNumber(){return number;};
    private:
    	int number;
    };
    
    class DerivedClass: public Base
    {
    public:
    	DerivedClass(int number,int _a)
    		:Base(number),a(_a)
    	{
    
    	}
    	int GetA(){return a;};
    
    private:
    	int a;
    };
    

     析构函数

    析构函数也是不能被继承的,不过在释放对象时,程序会首先调用派生类的析构函数,然后在调用基类的析构函数。

    赋值操作符不能被继承

    如果基类构造函数使用new来初始化指针,则必须提供显示的赋值操作符,对于派生类对象的基类部分,C++将使用基类的赋值操作符,所以不需要为派生类重新定义赋值操作符。

    如果派生类也使用了new,则必须提供显示赋值操作符。如:

    class Base
    {
    public:
    	//构造函数
    	Base(int a):number(a)
    	{
    		ch = new char;
    		*ch = 'A';
    	}
    	virtual ~Base()
    	{
    		delete ch;
    	}
    	//赋值操作符
    	Base & operator=(const Base & bs)
    	{
    		if(this == &bs)
    			return *this;
    		delete ch;
    		ch = new char;
    		*ch = *(bs.ch);
    		number = bs.number;
    		return *this;
    	}
    
    	virtual void Show()
    	{
    		cout << "Base:number=" << number << " ch=" << *ch << endl;
    	}
    private:
    	int number;
    	char *ch;
    };
    
    class DerivedClass: public Base
    {
    public:
    	DerivedClass(int number,int _a)
    		:Base(number),a(_a)
    	{
    		ch2 = new char;
    		*ch2 = 'B';
    	}
    	~DerivedClass()
    	{
    		delete ch2;
    	}
    	//赋值操作符
    	DerivedClass & operator=(const DerivedClass & dc)
    	{
    		if(this == &dc)
    			return *this;
    		Base::operator=(dc);	//调用父类的赋值操作符
    		a = dc.a;
    		delete ch2;
    		ch2 = new char;
    		*ch2 = *(dc.ch2);
    		return *this;
    	}
    
    	void Show()
    	{
    		Base::Show();
    		cout << "Derived:a=" << a << " ch2=" << *ch2 << endl;
    	}
    private:
    	int a;
    	char *ch2;
    };
    

     友元函数不能被继承

    友元函数并非成员函数,因此不能被继承

  • 相关阅读:
    网络日志流量分析-第一部分.doc
    Azkaban.Sqoop_网站流量日志分析2
    飞机加油问题
    9个点画10条直线,要求每条直线上至少3个点
    vector
    Selenium VS Webdriver
    B/S测试与C/S测试之区别
    几款代码比较工具
    单元测试-圈复杂度计算
    为什么并行测试很困难以及如何使用 ConTest 辅助测试
  • 原文地址:https://www.cnblogs.com/cmranger/p/4131194.html
Copyright © 2020-2023  润新知