C++默默编写函数的规则

易忘知识点:

  • 编译器产生出的析构函数不是虚析构函数,除非这个类的基类自身声明了虚析构函数。
  • 如果某个基类将赋值操作符声明为private,编译器将拒绝为其派生类生成赋值操作符。因为编译器想象调用基类的赋值操作符。

结论1:编译器生成的拷贝构造函数,对类成员调用类成员的拷贝构造函数来创建类成员并初始化,对内置类型成员拷贝每一个bits来创建内置成员并初始化。

代码段1:NameObject.h文件

#ifndef NAMEOBJECT_H
#define NAMEOBJECT_H

#include <string>

template <typename T>
class CNameObject
{
public:
    CNameObject(const std::string& name, const T& object):m_NameValue(name), m_ObjectValue(object){}
    /*这部分代码等价于编译器生成的拷贝构造函数的功能
    CNameObject (CNameObject& rhs):m_NameValue(rhs.GetNameValue()),m_ObjectValue(rhs.GetObjectValue()){}
    std::string& GetNameValue() {return m_NameValue;}
    T& GetObjectValue() {return m_ObjectValue;}*/
private:
    std::string m_NameValue;
    T m_ObjectValue;
};

结论2:编译器生成赋值操作符的条件是,生成得到的代码是合法的,例如类成员中有一个引用成员和一个const成员,我们已知引用变量和const变量均不能赋值,因此如果编译器为这两个变量定义赋值动作会使得编译器不知如何是好,这时编译器放弃为该类创建赋值操作符(无论此时所有成员均是引用变量和const变量,还是只有部分成员是引用变量和const变量)。此时如果你仍想让该类型支持赋值操作符,则必须自己定义。

代码段2.1:NameObject2.h文件

#ifndef NAMEOBJECT2_H
#define NAMEOBJECT2_H

#include <string>

template <typename T>
class CNameObject2
{
public:
    CNameObject2(std::string& name, const T& object/*, int a*/):m_NameValue(name), m_ObjectValue(object)/*, m_Spec(a)*/{}
private:
    std::string& m_NameValue;
    const T m_ObjectValue;
    /*int m_Spec;*/
};

#endif

代码段2.2:main.cpp文件

#include "NameObject.h"
#include "NameObject2.h"
#include <string>

int main()
{
    std::string s1 = "abc";
    std::string s2 = "def";
    CNameObject2<int> n1(s1,5/*,3*/);
    CNameObject2<int> n2(s2,4/*,2*/);
    n2 = n1;    //error
    return 0;
}

时间: 2024-12-28 02:17:27

C++默默编写函数的规则的相关文章

Effective C++ 之 Item 5:了解C++默默编写并调用哪些函数

Effective C++ chapter 2. 构造 / 析构 / 赋值运算 (Constructors, Destructors, and Assignment Operators) Item 5. 了解 C++ 默默编写并调用哪些函数 (Know what functions C++ silently writes and calls)

Effective C++ Item 5 了解 C++ 默默编写并调用哪些函数

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 经验: 如果你自己没声明,编译器会自动声明copy constructor,copy assignment,destructor, 如果你没有声明任何构造函数,编译器会自动声明default constructor 示例: 如果你写下 class Empty{ }; 将会等价于 class Empty{ public: Empty() {...} //default构造函数 Empty(c

EC笔记,第二部分:5.了解C++默默编写并调用哪些函数

5.了解C++默默编写并调用哪些函数 1.C++空类 C++会为一个空类建立以下函数 (1).默认构造函数 (2).默认拷贝构造函数 (3).析构函数 (4).赋值运算符(如果成员包含引用类型或const类型,不会生成赋值运算符)(引用的对象和const对象不可更改,所以无法重新赋值) class cl1 { public: int a; cl1(int t):a(t) {}; }; class cl2 { public: int &a; cl2(int t):a(t) {} }; int ma

cleanCode[2]:函数编写的几大规则

函数编写的几大规则 很难一开始就遵循这些规则,但是可以先想什么就写什么,然后再打磨它. 1.短小 函数的第一规则是短小,第二规则是还要更短小. if.else.while语句等,其中的代码块应该只有一行. 2.只做一件事 函数应该做一件事,做好这件事,只做这一件事. 编写函数毕竟是为了把大一些的概念拆分成另一抽象层上的一系列步骤. 3.自顶向下读代码:向下规则 我们想要让代码拥有自顶向下的阅读顺序.让每个函数后面都跟着位于下一抽象层级的函数,这样在查看函数列表时,就能循抽象层级向下阅读. 4.函

Python之编写函数

Python之编写函数 在Python中,定义一个函数要使用 def 语句,依次写出函数名.括号.括号中的参数和冒号:,然后,在缩进块中编写函数体,函数的返回值用 return 语句返回. 我们以自定义一个求绝对值的 my_abs 函数为例: def my_abs(x): if x >= 0: return x else: return -x 请注意,函数体内部的语句在执行时,一旦执行到return时,函数就执行完毕,并将结果返回.因此,函数内部通过条件判断和循环可以实现非常复杂的逻辑. 如果没

编写函数,以读模式打开一个文件,将其内容读入到一个string的vector中,将每一行作为一个对立的元素存于vector中

#include<iostream> #include<string> #include<vector> #include<fstream> using namespace std; int main(int argc,char *argv[]) { ifstream input(argv[1]); vector<string> vec; string tmp; while(getline(input,tmp)) { vec.push_back(

【C语言】编写函数实现库函数atof

//编写函数实现库函数atof #include <stdio.h> #include <assert.h> #include <ctype.h> #include <math.h> double calculate(const char *src, int flag) { double num = 0.0; int n = 0; int count = 0; while (*src) { if ((*src >= '0') && (*

编写函数返回值value的二进制模式从左到右翻转后的值

编写函数: unsigned int  reverse_bit(unsigned int value); 这个函数的返回值value的二进制位模式从左到右翻转后的值. 例如: 在32位机器上25这个值包含下列各位: 00000000000000000000000000011001 翻转后:(2550136832) 10011000000000000000000000000000 程序结果返回: 2550136832 观察输出的结果是将输入的数的二进制逆序排列的值. 代码如下: #include<

已知strcpy的函数原型:char *strcpy(char *strDest, const char *strSrc),编写函数 strcpy

已知strcpy的函数原型:char *strcpy(char *strDest, const char *strSrc)其中strDest 是目的字符串,strSrc 是源字符串.不调用C++/C 的字符串库函数,请编写函数 strcpy. /*编写strcpy函数(10分)已知strcpy函数的原型是??? char *strcpy(char *strDest, const char *strSrc);??? 其中strDest是目的字符串,strSrc是源字符串.(1)不调用C++/C的字