C++ Primer复制控制 13.1复制构造函数

c++构造函数/复制构造/赋值函数 c++中对象创建时必然会调用类中的构造函数以给类成员赋值,还有在c++中对象的复制必然调用复制构造函数,对象之间的赋值必然会调用赋值函数,最后在对象释放时必然会调用析构函数。之前在刚学习c++时,总是对类成员的初始化顺序,什么时候调用复制构造函数,什么时候调用赋值函理解混乱,今天在回看c++ primer plus的时候,突然感觉应该梳理一遍c++默认函数系列 阅读详情

※复制构造函数、赋值操作符和析构函数总称为复制控制。编译器自动实现这些操作,但类也可以定义自己的版本。

※有一种特别常见的情况需要类定义自己的复制控制成员的:类具有指针成员。

13.1 复制构造函数

         ※当用于类类型对象时,初始化的复制形式和直接形式有所不同:直接初始化直接调用与实参匹配的构造函数,复制初始化总是调用复制构造函数。复制初始化首先使用指定构造函数创建一个临时对象(第 7.3.2 节),然后用复制构造函数将那个临时对象复制到正在创建的对象

         ※由于不能复制 IO 类型的对象(第 8.1 节),所以不能对那些类型的对象使用复制初始化。

         ※作为一般规则(第9.1.1 节),除非你想使用容器元素的默认初始值更有效的办法是,分配一个空容器并将已知元素的值加入容器。

         ※拷贝构造函数是一种特殊的构造函数,函数的名称必须和类名称一致,它必须的一个参数是本类型的一个引用变量。

 

         二.拷贝构造函数的调用时机:

         1.复制一个对象,将它作为实参传给一个函数。

         2.从函数返回时复制一个对象。

   3.根据另一个同类型的对象显式或隐式初始化一个对象。

         4.初始化顺序容器中的元素。

         5.根据元素初始化式列表初始化数组元素。

我们来看看前三种情况:

#include <iostream>
using namespace std;
 
/*******************************************************/
class CExample {
public:
      /* 构造函数*/
      explicit CExample(int b = 10);
 
      /* 拷贝构造函数*/
      CExample( const CExample &obj);
 
      /* 析构函数*/
      ~CExample(){
           cout<<"indelete function. member address:"<<&a<<endl;
      }
 
      /* 一般函数*/
      void Show (){
           cout<<a<<endl;
      }
private:
      int a;
};
 
CExample::CExample(int b ):a(b){
      cout<<"memberaddress(in order to define which obj):"
           <<&a<<endl;
}
CExample::CExample(const CExample &obj){
      cout<<"in copyconstructor."<<endl;
      a = obj.a;
}
/*******************************************************/
 
/* 1.传入的是对象,如果传入的是对象的引用,则不会调用拷贝构造函数 */
void glob_fun1(CExample C) 
{ 
      cout<<"inglob_fun1"<<endl;
} 
 
/*2.从函数返回时复制一个对象。*/
CExample glob_fun2() 
{ 
      cout<<"inglob_fun1"<<endl;
      CExample temp(0); 
      return temp; 
}
 
/*******************************************************/
 
int main(){
 
      CExample A;
 
 
      /* 1. 对象以值传递的方式传入函数参数时,如何调用拷贝构造函数*/
//    glob_fun1(A);
      /*
           调用glob_fun1()时,会产生以下几个重要步骤:
           (1).A对象传入形参时,会先会产生一个临时变量,就叫C 吧。
           (2).然后调用拷贝构造函数把A的值给C。整个这两个步骤有点像:CExampleC(A);
           (3).等glob_fun1()执行完后, 析构掉C 对象。
      */
 
      /*2. 对象以值传递的方式从函数返回*/
//    glob_fun2();
      /*
           当g_Fun()函数执行到return时,会产生以下几个重要步骤:
           (1). 先会产生一个临时变量,就叫XXXX吧。
           (2). 然后调用拷贝构造函数把temp的值给XXXX。整个这两个步骤有点像:CExampleXXXX(temp);
           (3). 在函数执行到最后先析构temp局部变量。
           (4). 等g_Fun()执行完后再析构掉XXXX对象。
      */
 
      /* 3.根据另一个同类型的对象显式或隐式初始化一个对象。
           下面两句都会调用拷贝构造函数
      */
//    CExample B =A;  
//    CExampleB(A); 
      cout<<"mainfun finished."<<endl;
      return 0;
}


我们再看看这种情况:

CExample glob_fun3(CExample C)   
{   
	
    cout<<"inglob_fun1"<<endl;  
    CExample D(C);    
    CExample E = D;    
    return E;   
}

结果为:


分析结果我们可以看到:当在传入实参发生了复制(假设为C), 在返回的时候就不会发生复制, 返回的的就是C了

※三. 浅拷贝和深拷贝

1.默认拷贝构造函数

    很多时候在我们都不知道拷贝构造函数的情况下,传递对象给函数参数或者函数返回对象都能很好的进行,这是因为编译器会给我们自动产生一个拷贝构造函数,这就是“默认拷贝构造函数”,这个构造函数很简单,仅仅使用“老对象”的数据成员的值对“新对象”的数据成员一一进行赋值,它一般具有以下形式:

Rect::Rect(const Rect& r)  
{  
    width = r.width;  
    height = r.height;  
} 

    当然,以上代码不用我们编写,编译器会为我们自动生成。但是如果认为这样就可以解决对象的复制问题,那就错了,让我们来考虑以下一段代码:

class Rect
{
public:
    Rect()      // 构造函数,计数器加1
    {
        count++;
    }
    ~Rect()     // 析构函数,计数器减1
    {
        count--;
    }
    static int getCount()       // 返回计数器的值
    {
        return count;
    }
private:
    int width;
    int height;
    static int count;       // 一静态成员做为计数器
};

int Rect::count = 0;        // 初始化计数器

int main()
{
    Rect rect1;
    cout<<"The count of Rect: "<<Rect::getCount()<<endl;

    Rect rect2(rect1);   // 使用rect1复制rect2,此时应该有两个对象
     cout<<"The count of Rect: "<<Rect::getCount()<<endl;

    return 0;
}

  这段代码对前面的类,加入了一个静态成员,目的是进行计数。在主函数中,首先创建对象rect1,输出此时的对象个数,然后使用rect1复制出对象rect2,再输出此时的对象个数,按照理解,此时应该有两个对象存在,但实际程序运行时,输出的都是1,反应出只有1个对象。此外,在销毁对象时,由于会调用销毁两个对象,类的析构函数会调用两次,此时的计数器将变为负数。

说白了,就是拷贝构造函数没有处理静态数据成员。

出现这些问题最根本就在于在复制对象时,计数器没有递增,我们重新编写拷贝构造函数,如下:

class Rect  
{  
public:  
    Rect()      // 构造函数,计数器加1  
    {  
        count++;  
    }  
    Rect(const Rect& r)   // 拷贝构造函数  
    {  
        width = r.width;  
        height = r.height;  
        count++;          // 计数器加1  
    }  
    ~Rect()     // 析构函数,计数器减1  
    {  
        count--;  
    }  
    static int getCount()   // 返回计数器的值  
    {  
        return count;  
    }  
private:  
    int width;  
    int height;  
    static int count;       // 一静态成员做为计数器  
}; 


2.浅拷贝

    所谓浅拷贝,指的是在对象复制时,只对对象中的数据成员进行简单的赋值,默认拷贝构造函数执行的也是浅拷贝。大多情况下“浅拷贝”已经能很好地工作了,但是一旦对象存在了动态成员,那么浅拷贝就会出问题了,让我们考虑如下一段代码:

class Rect  
{  
public:  
    Rect()      // 构造函数,p指向堆中分配的一空间  
    {  
        p = new int(100);  
    }  
    ~Rect()     // 析构函数,释放动态分配的空间  
    {  
        if(p != NULL)  
        {  
            delete p;  
        }  
    }  
private:  
    int width;  
    int height;  
    int *p;     // 一指针成员  
};  
  
int main()  
{  
    Rect rect1;  
    Rect rect2(rect1);   // 复制对象  
    return 0;  
}  


    在这段代码运行结束之前,会出现一个运行错误。原因就在于在进行对象复制时,对于动态分配的内容没有进行正确的操作。我们来分析一下:

    在运行定义rect1对象后,由于在构造函数中有一个动态分配的语句,因此执行后的内存情况大致如下:

 

 

    在使用rect1复制rect2时,由于执行的是浅拷贝,只是将成员的值进行赋值,这时 rect1.p= rect2.p,也即这两个指针指向了堆里的同一个空间,如下图所示:

 

当然,这不是我们所期望的结果,在销毁对象时,两个对象的析构函数将对同一个内存空间释放两次,这就是错误出现的原因。我们需要的不是两个p有相同的值,而是两个p指向的空间有相同的值,解决办法就是使用“深拷贝”。


3.
深拷贝

    在“深拷贝”的情况下,对于对象中动态成员,就不能仅仅简单地赋值了,而应该重新动态分配空间,如上面的例子就应该按照如下的方式进行处理:

class Rect  
{  
public:  
    Rect()      // 构造函数,p指向堆中分配的一空间  
    {  
        p = new int(100);  
    }  
    Rect(const Rect& r)  
    {  
        width = r.width;  
        height = r.height;  
        p = new int;    // 为新对象重新动态分配空间  
        *p = *(r.p);  
    }  
    ~Rect()     // 析构函数,释放动态分配的空间  
    {  
        if(p != NULL)  
        {  
            delete p;  
        }  
    }  
private:  
    int width;  
    int height;  
    int *p;     // 一指针成员  
}; 


此时,在完成对象的复制后,内存的一个大致情况如下:

 

此时rect1的p和rect2的p各自指向一段内存空间,但它们指向的空间具有相同的内容,这就是所谓的“深拷贝”。

 

※

※3. 防止默认拷贝发生

    通过对对象复制的分析,我们发现对象的复制大多在进行“值传递”时发生,这里有一个小技巧可以防止按值传递——声明一个私有拷贝构造函数。甚至不必去定义这个拷贝构造函数,这样因为拷贝构造函数是私有的,如果用户试图按值传递或函数返回该类对象,将得到一个编译错误,从而可以避免按值传递或返回对象。

// 防止按值传递
class CExample 
{
private:
	int a;

public:
	//构造函数
	CExample(int b)
	{ 
		a = b;
		cout<<"creat: "<<a<<endl;
	}

private:
	//拷贝构造,只是声明
	CExample(const CExample& C);

public:
	~CExample()
	{
		cout<< "delete: "<<a<<endl;
	}

    void Show ()
	{
        cout<<a<<endl;
    }
};

//全局函数
void g_Fun(CExample C)
{
	cout<<"test"<<endl;
}

int main()
{
	CExample test(1);
	//g_Fun(test); 按值传递将出错
	
	return 0;
} 


四.拷贝构造函数的几个细节

1. 拷贝构造函数里能调用private成员变量吗?
解答:
这个问题是在网上见的,当时一下子有点晕。其时从名子我们就知道拷贝构造函数其时就是一个特殊的构造函数,操作的还是自己类的成员变量,所以不受private的限制。

 

2. 以下函数哪个是拷贝构造函数,为什么?

X::X(const X&);    
X::X(X);    
X::X(X&, int a=1);    
X::X(X&, int a=1, int b=2);

解答:对于一个类X, 如果一个构造函数的第一个参数是下列之一:
a) X&
b) const X&
c) volatile X&
d) const volatile X&
且没有其他参数或其他参数都有默认值,那么这个函数是拷贝构造函数.

X::X(const X&);  //是拷贝构造函数    
X::X(X&, int=1); //是拷贝构造函数   
X::X(X&, int a=1, int b=2); //当然也是拷贝构造函数

3. 一个类中可以存在多于一个的拷贝构造函数吗?

解答:类中可以存在超过一个拷贝构造函数。

class X { 
public:       
  X(const X&);      // const 的拷贝构造
  X(X&);            // 非const的拷贝构造
};
注意,如果一个类中只存在一个参数为 X& 的拷贝构造函数,那么就不能使用const X或volatile X的对象实行拷贝初始化.

class X {    
public:
  X();    
  X(X&);
};    

const X cx;    
X x = cx;    // error

如果一个类中没有定义拷贝构造函数,那么编译器会自动产生一个默认的拷贝构造函数。

这个默认的参数可能为 X::X(const X&)或 X::X(X&),由编译器根据上下文决定选择哪一个。

 



 

 

C++中拷贝构造函数调用时机 C++中拷贝构造函数调用时机通常有三种情况 1、使用一个已经创建完毕得对象来初始化一个新对象 2、值传递的方式给函数参数传值 3、以值方式返回局部对象 阅读详情

相关推荐

《C++ Primer》导学系列:第 13 章 - 拷贝控制

本节总结掌握了拷贝控制的基本概念和操作,包括拷贝构造函数、拷贝赋值运算符和析构函数。理解了拷贝控制函数在对象复制、赋值和销毁过程中的作用和调用时机。学会了在类中正确实现拷贝控制函数,以确保对象在不同生命周期阶段的正确行为。理解了“三/五法则”的重要性,学会了在类设计中同时实现必要的拷贝控制函数和移动语义。掌握了如何通过delete关键字阻止对象的拷贝和赋值。提高建议多练习拷贝控制函数的实现:通过编写更多涉及拷贝控制的类,熟悉各种管理方法的用法,提高对拷贝控制的理解和实现能力。

iShare_Carlos的博客 1731

【c++primer——】第13章复制控制——01深入理解复制构造函数

13. 理解复制控制成员和构造函数的一个良好方式是定义一个简单类,该类具有这些成员,每个成员打印自己的字: struct Exmp1  {  Exmp1() { std::cout  编写一个像Exmp1这样的类,给出复制控制成员和其他构造函数。然后写一个程序,用不同方式使用Exmp1类型的对象:作为非引用和引用形参传递,动态分配,放在容器中,等等,研究何时执行哪个构造函数和复制控制成员,可以帮

蝉之洞 509

深信服AF设置安全防护策略

防火墙设置安全防护策略,禁止用户访问指定网站

m0_64423407的博客 4844

C++11六大函数(构造函数,移动构造函数,移动赋值操作符,复制构造函数,赋值操作符,析构函数)

前言: 在C++中,有三大函数复制控制(复制构造函数,赋值操作符,析构函数),而在C++11中,加入了移动构造函数,移动赋值操作符。我就斗胆将他们命名为六大函数好了。 一、构造函数 c++primer中说过:构造函数是特殊的成员函数,只要创建类类型的新对象,都要执行构造函数。构造函数的工作就是保证每个对象的数据成员具有合适的初始值。 构造函数与其他函数不同:构造函数和类同名,没有返回类型。 构造函数与其他函数相同:构造函数也有形参表(可为void)和函数体。 (参数表为void的构造函数为默认构.

xujianjun229的博客 1752

CXL协议-第三章 CXL事务层

CXL.io为I/O设备提供了一个非一致的负载/存储接口。图3-1显示了Flex总线分层层次结构中的位置。事务类型、事务分组格式、基于信用的流量控制、虚拟通道管理和事务排序规则遵循PCIe*定义,详情请参考PCIe基础规范的“事务层规范”章节。本章重点介绍了用于CXL.io的著名的PCIe操作模式或特性。

qq_41305217的博客 2769

【mysql8.0.33安装详情教程】

8、进入Account and Roles界面,输入密码,再点击next(密码随便输,自己记住就行)11、进入Apply Configuration界面,直接点Execute,等待应用成功。14、输入密码,点击check,检查是否正确。3、下图是选择安装类型,选择默认安装就可以,然后点击“next”。5、进入Product Configuration,点击next。9、进入Windows Service界面,直接点击next。15、点击Execute执行安装(完成后点击Finish)二、验证是否安装成功。

98渣渣辉的博客 2114

020_拷贝构造函数的四种调用时机

/* copy构造函数的调用 时机1 时机2 */ #if 1 class Test4 { public: Test4() //无参数构造函数 { m_a = 0; m_b = 0; cout &amp;amp;amp;lt;&amp;amp;amp;lt; &amp;amp;quot;我是构造函数,自动被调用了&amp;amp;quot; &amp;amp;amp;lt;&amp;

吾竹清风2017 1789

cmu15445(2024fall) project 2

project 2比p1难度要更大,代码量更大且涉及的知识更多,实现中出现的bug更多,好在是最后全部解决了。我最大的收获在于对于多线程编程的理解更深入了,实际发现解决了多个多线程相关的bug,学会了更多多线程下debug的技巧方法,也见识了更多多线程的bug情况。在之后可以更系统的学习一下多线程编程。同时学会实现B+树也是需要掌握的基础。

Jerome_Yi的博客 1561

【C++ primer】第13章 复制控制 (1)

学习类如何控制该类类型的对象在被复制、赋值、移动、销毁时做什么。

HPP_优快云的博客 428

【论文翻译】Enhancing Channel Estimation in High Mobility OTFS Systems: A Novel Pilot-Based Method...

本文介绍了一种用于正交时频空间(OTFS)调制系统的新型基于导频的信道估计方法。我们提出的方法是在ZP-OTFS系统的零填充区域插入一行导频符号,具有减少开销和降低峰均功率比(PAPR)的显著优势。特别是,通过沿多普勒轴分布导频符号,我们的方法在高移动性场景下依然能够提供鲁棒且精确的信道估计,这是像TransPod这种时速超过1000 km/h的运输系统的一个典型特征。这一点至关重要,因为在此类场景下,多普勒频移可能会导致系统性能的严重退化。

Cuby的博客 1212

Android13配置selinux让system应用可读sys,proc,SN号

Android13预置的system应用,需要读/sys, /proc目录,读(SN)serial number号, 需要修改selinux配置,否则会报avc错.其修改方法会比Android11复杂一些.。

zmlovelx(帅得不敢出门 程序员群31843264) 2654

【C++ primer】第13章 复制控制 (2)

学习类如何控制该类类型的对象在被复制、赋值、移动、销毁时做什么。掌握移动构造函数和移动赋值运算符的实现。

HPP_优快云的博客 439

K-Core, K-Shell & K-Crust傻傻分不清楚

K-Core(K-核)就是所有大于等于K的K-Shell的并集;K-Crust(K-皮)就是所有小于等于K的K-shell的并集。

欢迎订阅 -- 小源笔迹 2256

《C++ Primer》第13章 拷贝控制(一)

在新标准下,我们可以通过将拷贝构造函数和拷贝赋值运算符定义为删除的函数(deleted function)来阻止拷贝。删除的函数是这样一种函数:我们虽然声明了它们,但不能以任何形式使用它们。在参数列表后面加上=delete=delete必须出现在函数第一次声明的时候,且可以对任何函数指定=delete。

MaTF_的博客 1247

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

复制控制(C++Primer_第13章)

C++复制控制 一、复制控制 类能控制复制,赋值,撤销该类的对象时的动作,分别通过下面的成员函数: 复制构造函数:具有单个形参,该形参是对该类类型的引用(通常用 const 修饰); 赋值操作符 析构函数:不管有没显示定义,编译器都自动执行类中非 static 数据成员的析构函数 这三个函数就成为复制控制。 二.为什么要研究复制控制 如果没有显示地定义复制构造函数和赋值操作符,编译器会为我们定义。 但是编译器合成的复制控制函数只做必需的工作,某些类如果依赖于默认的定义会导致错误,例如类具有指

qq_43169752的博客 257

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

理解何时执行哪个构造函数和复制控制成员

C++ Primer第四版 习题13.14 理解复制控制成员和构造函数的一个良好方式是定义一个简单的类,该类具有这些成员,每个成员打印自己的名字: struct Exmpl {    Exmpl() {std::cout    Exmpl(const Exmpl&)    { std::cout    //... }; 编写一个像Exmpl这样的类,给出复制控制成员和其他构造函

liubaoli1989的专栏 925

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

C++ Primer 13-15

再读C++ Primer 第十三章:复制控制 复制构造函数是一种特殊构造函数,具有单个形参,该形参是对该类类型的引用。当定义一个新对象并用一个同类型的对象对它进行初始化时,将显式使用复制构造函数。当将该类型的对象传递给函数或从函数返回该类型的对象时,将隐式使用复制构造函数。 析构函数是构造函数的互补:当对象超出作用域或动态分配的对象被删除时,将自动应用析构函数。析构函数可用于释放对象

walkerkalr的专栏 702

TeamAI 自动同步揭秘:AI 会话如何静默获取团队最新资源的完整指南

TeamAI 是一款开源的 AI 团队资源管理 CLI 工具(teamai-cli),它的自动同步机制可以让 Claude Code、Codex、Cursor 等 AI 助手在**每次会话启动时静默拉取团队最新的技能、规则与知识**,全程无需人工干预。本文带你彻底搞懂这套机制背后的原理。✨ ## 什么是 TeamAI 自动同步? 想象这样一个场景:管理员更新了团队的编码规则,昨天还有效的技能今

gitblog_01132的博客 993

C++ Primer:第13章 拷贝控制

第13章 拷贝控制 拷贝控制操作:拷贝构造函数、拷贝赋值运算符、移动构造函数、移动赋值运算符、析构函数。 当类中没有声明构造函数时,编译器会在其需要时生成合成默认构造函数。当类中没有定义拷贝构造函数时,编译器生成合成拷贝构造函数。合成拷贝赋值运算符、合成析构函数与合成拷贝构造函数类似。当类中没有自定义拷贝控制成员,且每个非static数据成员都可以移动时,编译器才会合成移动构造函数或移动赋值运算符。 若一个类需要析构函数,则几乎肯定需要拷贝构造函数、拷贝赋值运算符;若一个类需要拷贝构造函数,则几乎肯定需.

北冥有鱼wyh的博客 587

Cpp-Primer-5th-Exercises项目揭秘:从基础语法到高级特性的完整路径

你是否正在学习C++编程语言,却被《C++ Primer》第五版中的复杂习题困扰?😅 别担心,Cpp-Primer-5th-Exercises项目为你提供了完整的习题解答指南!这个开源项目包含了《C++ Primer》第五版所有章节的习题解答,从基础语法到高级特性,为你搭建了一条清晰的学习路径。无论你是C++初学者还是希望巩固知识的开发者,这个项目都是你学习路上的得力助手。 ## 📚 项目概

gitblog_00578的博客 846

C++ Primer第13章 拷贝控制

C++Premier 学习笔记(第十三章 拷贝控制(13.1)) 文章目录一、13.1 拷贝、赋值与销毁13.1.1 拷贝构造函数13.1.2 拷贝复制运算符13.1.3 析构函数13.1.4 三/五法则13.1.5使用=default13.1.6阻止拷贝总结 一、13.1 拷贝、赋值与销毁 13.1.1 拷贝构造函数 注意:拷贝构造函数的第一个参数必须是一个引用类型,拷贝构造函数通常不应该是explict的 合成拷贝构造函数 如果我们没有定义拷贝构造函数,编译器会给我们定义一个,与合成默认构造函数

zzh123353的博客 456

C++primer13章习题

//13.3假定Point为类类型,该类类型有一个复制构造函数,指出下面程序段中每一个试用了复制构造函数的地方。   Point global;   //默认构造函数 Point foo_bar(Point arg)    //复制构造函数 {     Pointlocal = arg;      //复制构造函数     Point*heap = ne

q344144460的专栏 1567

c++ 拷贝构造函数_【笔记】C++Primer—— 第13章:拷贝控制

好久不见,回来更新了。这一章介绍了对类的拷贝控制的操作,其中最重要的是13.1对类的五大基本操作函数的理解和13.6对右值引用和对象移动的理解,比较长需要慢慢看。这章的13.1是面向对象编程非常重要的一部分,而13.6的右值引用则几乎是C11最重要的新特性,值得重点理解。从这开始是第三部分"类设计者的工具"了,都是C++最区别于C的地方。13.1 拷贝,赋值与销毁我们...

weixin_39781363的博客 228

C++ PRIMER 第十三章 复制控制

第13章 复制控制   当定义一个新类型的时候,需要显式或隐式地指定复制、赋值和撤销该类型的对象时会发生什么,这是通过定义特殊成员:复制构造函数、赋值操作符和析构函数来达到的,复制构造函数、赋值操作符和析构函数总称为复制控制,编译器自动实现这些操作,但类也可以定义自己的版本 #include <iostream> using namespace std; class A{ p...

金色的省略号 127

C++ Primer(第五版) 13.1.6节练习

13.18 Employee类及其测试代码如下: #include <iostream> #include <string> using namespace::std; class Employee { friend void get_info(const Employee &s); public: Employee() { id = num++;...

wlli1985的博客 486
上一篇: C++ Primer 类 12.4 explicit 构造函数
下一篇: C++ Primer复制控制 13.2 赋值操作符
big_bit
博客等级 码龄11年 67粉丝 40原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值