首页 > 编程语言 >C++ 合成默认构造函数

C++ 合成默认构造函数

时间:2024-03-21 12:00:14浏览次数:38  
标签:default constructor 默认 编译器 C++ 基类 class 构造函数

问题:C++面向对象编程时,如果我们没有声明任何构造函数constructor,按照以前最初学习,说编译器会自动合成一个默认的无参构造函数default constructor,但是事实确实是这样吗,存不存在例外呢,即使有合成构造函数,那么它又将对类数据进行怎样的初始化呢?

1. 问题一

如果我们没有声明任何构造函数,编译器不会在任何时候都会合成一个默认的无参构造函数!如果该类的数据成员都是基本数据类型:如:int、char、double、float等,那么编译器不会合成一个默认构造函数。用书中的话说就是:这样如果合成的构造函数是trivial(浅薄无能的,没啥用的)。

#include<iostream>
using namespace std;
 
class test
{
//类其他函数,但不含构造函数哦
public:
	int i;
	double j;
};
 
void main()
{
	test t; //哈哈,事实证明这个类并没有被编译器合成缺省构造函数哦!
	cout << t.i << "  " << t.j << endl;
	system("pause");
}

2. 那什么时候编译器不会合成默认构造函数呢?

  • 类中没有虚函数,没有继承虚基类;

  • 类的任何非静态数据成员没有大括号或等号初始化;

  • 直接继承的基类没有默认构造函数;

  • 所有的非静态数据成员没有默认构造函数;

3. 那什么时候编译器会合成默认构造函数呢?

四种情况下会合成default constructor:

  • 带有default constructor 的成员类对象( member class object);

  • 带有default constructor 的基类(base class)的类;

  • 带有虚函数(virtual functions)的类;

  • 带有虚基类(virtual class)的类;

3.1 带有default constructor 的成员类对象

此种情况下编译器会合成一个构造函数,以调用成员类的default constructor。

class base
{
public:
	base(){}
};
class test
{
public:
	int i;
	double j;
	base ba;
};

这时编译器会在成员类的 default constructor被调用的时候合成的构造函数,比如声明子类对象时,如果成员类的 default constructor没有被调用时是不会合成的构造函数。

3.2 带有default constructor 的基类的类

一个类继承自有default constructor 的基类,那么编译器会在需要时合成一个构造函数,并优先调用基类default constructor;对于继承链(比如B继承A,C继承B)也是如此。

如果子类中有多个用户自定义constructor,那么编译器会对没一个constructor做出相应修改,修改方式和上述相关内容相同,但是不会合成一个子类default constructor;如果同时存在:带有default constructor的基类和带有default constructor的类成员对象,那么子类构造函数会先按照基类顺序调用其default constructor,再按照声明顺序调用成员类的default constructor。

3.3 带有虚函数的类

此种情况也包含两种情况:

  • class声明或继承一个virtual functions;

  • class派生自一个继承串链,其中有一个或多个virtual functions;

那么在编译期间会发生:

  • 一个virtual function table(虚函数表)被编译器产生出来,内放class的virtual functions地址;

  • 在每一个子类对象中,一个额外的vptr(虚函数指针)会被合成,内含相关class的virtual function table地址;

所以这样必须要一个构造函数来初始化每一个类对象中的vptr。

class Point {
  public:
    virtual void print() const;
  private:
    int x;
    int y;
};

//编辑器合成的构造函数
Point::Point() {
    this->_vptr = 0xXXX;
}

3.4 带有虚基类的类

虚继承也会在子类对象中被合成一个指向虚基类的指针,因此也要被初始化,所以必须要构造函数,虚基类或者虚继承保证子类对象中只有一份虚基类的对象,特别是对于多重继承更是很重要。

4. 两个误区:

  1. 任何class 如果没有定义default constructor 多会被合成出来的;

  2. 编译器合成出来的default constructor 会显示的初始化该类的每一个数据成员。

标签:default,constructor,默认,编译器,C++,基类,class,构造函数
From: https://www.cnblogs.com/love-9/p/18087067

相关文章

  • C++ RTTI
    1.背景RTTI的英文全称是"RuntimeTypeIdentification",中文称为"运行时类型识别",它指的是程序在运行的时候才确定需要用到的对象是什么类型的。用于在运行时(而不是编译时)获取有关对象的信息。在C++中,由于存在多态行为,基类指针或者引用指向一个派生类,而其指向的真正类型,在编译阶......
  • C++标准库容器选择
    C++标准库提供了多种容器,每种容器都有其自身的特点和适用场景。以下是C++标准库中常用的容器以及它们的特点:std::vector:动态数组,支持随机访问,适用于需要快速随机访问元素的场景。std::list:双向链表,支持快速插入和删除操作,适用于需要频繁插入和删除元素的场景。std::deque......
  • C++基础入门(命名空间,函数,引用)
    文章目录前言1,命名空间2,函数函数重载缺省参数内联函数3,引用尾声前言欢迎来到这篇关于C++的入门博客!C++是一门强大而又广泛应用的编程语言,作为一门面向对象的编程语言,C++可以让你更好地组织和管理代码,提高代码的重用性和可维护性。它广泛应用于游戏开发、嵌入式系......
  • C++ 参数传递浅析
    全文目录概述值传递(pass-by-value)什么是变量?值传递的例子指针传递(pass-by-pointer)什么是指针?指针传递的例子引用传递(pass-by-reference)什么是引用?引用和指针的异同引用传递的例子写在最后小结概述众所周知C++参数传递有三种,分别问值传递、指针传递、引用传......
  • C++内置 new /delete 运算符浅析
    全文目录malloc()/free()原型解析简化版本用法举例new/delete静态/动态类型new/delete运算符原型常用但没有注意区分的例子使用new分配对象的生存期那new/delete都做什么事呢几个注意点写在最后malloc()/free()提到new/delete运算符就不得不说malloc()/f......
  • C++模板实现之谜:为何只能在头文件中?解密原因与高级分离技术
     概述:C++中模板必须在头文件中实现,因为编译器需要可见的实现以生成模板具体实例的代码。通过头文件,确保模板在每个编译单元中都能被正确展开,提高可维护性。在C++中,模板只能在头文件中实现的主要原因是编译器在使用模板时需要生成对应的代码,而这部分代码必须在编译时可见。以......
  • python中出现Microsoft Visual C++ 14.0 or greater is required
    我尝试下载了Microsoftvisualc++14.0,但是依然不管用,而且它是真的很大…… 直接安装相应依赖也不管用(可能其他人管用?)——condainstalllibpythonm2w64-toolchain-cmsys2链接:https://blog.csdn.net/qzzzxiaosheng/article/details/125119006 然后我有找到一个,看着描......
  • C++ 函数模板
    C++函数模板函数模板在C++中,函数模板是一种允许函数以一种类型无关的方式来操作的工具。它们使得函数能够处理不同类型的数据而不需要为每种类型编写重复的代码。函数模板的核心思想是“参数化类型”,这意味着在定义函数时,可以使用一个或多个通用类型参数,而在函数被调用时......
  • C++ 编程入门指南:深入了解 C++ 语言及其应用领域
    C++简介什么是C++?C++是一种跨平台的编程语言,可用于创建高性能应用程序。C++是由BjarneStroustrup开发的,作为C语言的扩展。C++为程序员提供了对系统资源和内存的高级控制。该语言在2011年、2014年、2017年和2020年进行了4次重大更新,分别为C++11、C++14、C+......
  • C++ 多重继承下的内存布局
    1.多重继承多重继承示例代码如下:classBase1{public:voidf0(){}virtualvoidf1(){}inta;};classBase2{public:virtualvoidf2(){}intb;};classDerived:publicBase1,publicBase2{public:voidd(){}voidf2(){}......