类中默认的函数

我们自己定义的类,或者C++标准里默认提供的类,我们都可以看成是区别于基本数据类型(char,int,double等)的新类型,比如我们使用int类型时,一般会有如下的一些操作,如:

  (1)int a;//定义一个变量

  (2)int a = 10;//定义一个变量并进行初始化操作

  (3)

    int a(10);

    int b = a;//定义一个变量,并对其进行初始化操作

  (4)

  void fun(int i){}

  int a = 10;

  fun(a);//定义一个变量并将其作为函数参数进行传递,函数参数的给值也是初始化操作

既然都是数据类型,那么其操作也是大同小异的。在一个没有任何成员函数的类,会有以下的默认函数(对于这些默认的函数,只要自己手动编写了这些函数,那么默认的就会被覆盖):

class Test
{
public:
    Test() {}//默认构造函数
    Test(const Test &t) {}//默认拷贝构造函数
    Test &operator=(const Test &t) {}//默认“=”运算符重载函数
    ~Test() {}//默认析构函数
};

  (a)默认无参构造函数(只要是构造函数,都没有返回值的)

    作用是让这个新的数据类型可以定义变量(对象),就像int a;

    此时,我们不能完成成员变量的初始化,要想完成成员变量的初始化,我们可以自己写一个构造函数,然后再初始化列表中进行成员变量的初始化(注意:初始化列表的执行顺序是从上到下,即成员变量的声明顺序)

  (b)默认拷贝构造函数

    参数是当前类的一个常量引用

    默认的拷贝构造是浅拷贝,当有成员变量时,浅拷贝时这样的:

class Test
{
public:
    int m_a;
public:
    Test() {}
    Test(const Test &t)
    {
        this->m_a = t.m_a;
    }
    Test &operator=(const Test &t) {}
    ~Test() {}
};

对于这种类型的变量时没问题的,但是当成员变量是其他类的指针变量时,那么就会让两个指针变量指向同一块空间,当我们用delete 指针变量时,就会删除同一块空间删除两次,这样就会导致程序奔溃,所以这种情况,我们需要自己手动编写拷贝构造函数,将那块空间也拷贝一份,这样程序就能正常运行了。

class Test{};

void fun(Test t);
Test fun2();

Test t1;
Test t2(t1);//调用默认的拷贝构造
Test t3 = t1;//调用默认的拷贝构造 这个和上面是一样的,只是写法不同
Test t4;
fun(t1);//调用默认的拷贝构造
t4 = fun2();//调用默认的拷贝构造

  (c)默认“=”运算符重载函数

class Test{};

Test t1;
Test t2;
t2 = t1;//调用默认“=”操作符重载函数

  注意:默认拷贝构造函数和默认“=”操作符重载函数都会检查对象是否初始化,比如:

class Test
{
public:
    int m_a;
};

int main()
{
    Test t1;
    Test t2;
    t2 = t1;//编译失败,使用了未初始化的局部变量"t1"
    Test t3 = t1;//编译失败,使用了未初始化的局部变量"t1"

    return 0;
}

  (d)析构函数

原文地址:https://www.cnblogs.com/chen-cai/p/9579323.html

时间: 2024-07-31 15:06:29

类中默认的函数的相关文章

QWidget类中默认是忽略inputMethodEvent事件(要获取输入的内容就必须使用这个事件)

因为项目的需要以及主管的要求,准备将工程移植到Qt中,这样就可以比较容易的实现跨平台了.因为之前工程是在windows下开发的,第一个平台又是mobile所以除了底层框架之外其他的都是使用的windows的API以及编程模式,现在要移植到Qt中,第一个要面临的问题就是如何将windows的消息机制很好的转换为Qt中的处理机制.windows中是消息,Qt中是事件和信号.槽,其实原理都是一样的. 1.常用事件 因为所有和界面相关的类都是继承自QWidget类,所以QWidget类有的时间和方法,在

(继承及其访问限定符)&&(派生类及其默认成员函数)&&(赋值兼容规则)

◆继承: ★继承概念 继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能.这样产生新的类,称派生类.继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程. 继承定义格式 ★继承关系&访问限定符 class Base { public: Base() { cout<<"B()" <<endl; } ~Base () { cout<<"~

在复数类中自定义类型转换函数实现复数和非复数之间的运算

实现复数+double型数据,并且打印运算后实部上的数据 #include <iostream> using namespace std; class Complex { public: Complex( )//定义默认构造函数初始化复数 { real=0; imag=0; } //使用初始化表初始化复数 Complex(double r, double i):real(r),imag(i){} //定义自定义类型转换函数 operator double() { return real; }

(继承及其访问限定符)&amp;&amp;(派生类及其默认成员函数)&amp;&amp;(赋值兼容规则)

◆继承: ★继承概念 继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能.这样产生新的类,称派生类.继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程. 继承定义格式 ★继承关系&访问限定符 class Base { public: Base() { cout<<"B()" <<endl; } ~Base () { cout<<"~

检测某个方法是否属于某个类中--解析php函数method_exists()与is_callable()的区别

php函数method_exists() 与is_callable()的区别在哪?在php面相对象设计过程中,往往我们需要在调用某一个方法是否属于某一个类的时候做出判断,常用的方法有 method_exists()和is_callable() 相比之下,is_callable()函数要高级一些,它接受字符串变量形式的方法名作为 第一个参数,如果类方法存在并且可以调用,则返回true.如果要检测类中的方法是否能被调用,可以给函数传递一个数组而不是类的方法名作为参数.数组必须包含对象或类名,以将其作

为什么类中的线程函数必须要声明静态

其实类的静态函数就跟全局函数是一个样子的, 只是调用的时候要加下个类修饰符而已. 至于为什么不能是非静态成员函数呢, 因为非静态成员函数都会在参数列表中加上一个this指针为为参数, 这样的话你写的线程函数就不符合调用规定了.比如 DWORD WINAPI ThreadFun(LPVOID); 是非静态的,实际编译后,就会变成DWORD WINAPI ThreadFun(LPVOID, CMyClass *this); 这个函数就明显不能作为线程的函数了, 因为多了个参数.所以编译就过不了了.

类中的回调函数

失败原因 由于类的成员函数有隐含的this指针传递,从而导致一个CALLBACK型的成员函数安装时函数参数个数不匹配. 解决方法 1)将回调函数挪出类外,并声明为友元 2)将回调函数生命为静态成员函数(使用回调函数的某个参数传递当前对象的this指针) 类中的回调函数,码迷,mamicode.com

Swift - AppDelegate.swift类中默认方法的介绍

项目创建后,AppDelegate类中默认带有如下几个方法,具体功能如下: 1,应用程序第一次运行时执行 这个方法只有在App第一次运行的时候被执行过一次,每次App从后台激活时都不会再执行该方法. (注:所有一般我们都在这里获取用户许可,比如本地消息推送的许可等) 1 2 3 4 func application(application: UIApplication,     didFinishLaunchingWithOptions launchOptions: [NSObject: Any

c++ 类中模版成员函数

C++函数模版与类模版. template <class T> void SwapFunction(T &first, T &second){ }//函数模版 template <class T>//类模版 class CTemplate{ public: void SWap(T &first, T &second){ } }; #include <iostream> class Single{ public: static Single