当前位置: 首页 > 编程日记 > 正文

c++, 派生类的构造函数和析构函数 , [ 以及operator=不能被继承 or Not的探讨]

说明:文章中关于operator=实现的示例,从语法上是对的,但逻辑和习惯上都是错误的。

参见另一篇专门探究operator=的文章:《c++,operator=》http://www.cnblogs.com/mylinux/p/4113266.html

1.构造函数与析构函数不会被继承;[1]

不是所有的函数都能自动地从基类继承到派生类中的。构造函数和析构函数是用来处理对象的创建和析构的,它们只知道对在它们的特殊层次的对象做什么。所以,在整个层次中的所有的构造函数和析构函数都必须被调用,也就是说,构造函数和析构函数不能被继承。
  另外,operator= 也不能被继承,因为它完成类似于构造函数的活动。//All overloaded operators except assignment (operator=) are inherited by derived classes.

2.派生类的构函数被调用时,会先调用基类的其中一个构造函数,因为在派生类的构造函数中用了初始化表的方式调用了基类构造函数,默认不写时是调用了基类中可以不传参数的构造函数。

3.在派生类对象释放时,先执行派生类析构函,再执行其基类析构函数。

#include <iostream>
using namespace std;
#include <string>class Basic
{
public:string m_name;Basic();Basic(string name);Basic(Basic& bc);~Basic();Basic& operator=(const Basic& bc) {cout << "Basic::operator=()\n";this->m_name = bc.m_name;return *this;}
};
Basic::Basic()
{cout <<"Basic::Basic()"<<endl;
}
Basic::Basic(string name)
{m_name = name ;cout <<"Basic::Basic(string)"<<"name:"<<m_name<<endl;
}
Basic::Basic(Basic &bc)
{this->m_name = bc.m_name;cout <<"Basic::Basic(Basic&)"<<"name:"<<bc.m_name<<endl;
}Basic::~Basic()
{cout<<"this is "<<m_name << "Basic::~Basic()"<<endl;;
}class Derived:public Basic
{
public:int m_dx;Derived();Derived(string name);//m_name~Derived();void show();
};
Derived::Derived()
{cout <<"Derived::Derived()"<<endl;
}
Derived::Derived(string name):Basic(name)
{cout <<"Derived::Derived(string)"<<"name:"<<m_name<<endl;
}
Derived::~Derived()
{cout <<"this is "<<m_name <<"Derived::~Derived()"<<endl;;
}
void Derived::show()
{cout<<"name: "<<m_name<<endl;
}
void test()
{Derived dc1("dc1");cout<<""<<endl;Derived dc2("dc2");//m_bxcout<<""<<endl;dc1 = dc2 ;//Basic::operator=() 调用了基类的operator= ,并正确地对Derived::m_name进行了赋值。 看起来是operator=被继承了?分析见下5补充。
cout
<<"next is dc1.show(): ";dc1.show();cout<<""<<endl; } int main() {test();while(1); } /** Basic::Basic(string)name:dc1 Derived::Derived(string)name:dc1Basic::Basic(string)name:dc2 //生成派生类对象时,先调用基类的构造函数 Derived::Derived(string)name:dc2 //在调用自身的构造函数Basic::operator=() //调用了基类的operator= ,并正确地对Derived::m_name进行了赋值。
            //测试时,假如把基类的operator=实现为空函数,那么Derived对象也不能对Derived::m_name进行重新赋值。除非再手动实现
Derived的operator=
            //operator= 只有一个,Drived中如果手动实现了,将会覆盖基类的=。就是说,不会执行基类的operator=。
next is dc1.show(): name: dc2 this is dc2Derived::~Derived() //析构和构造的调用顺序刚好相反。先调用自身的析构函数,再调用基类的析构函数。 
this is dc2Basic::~Basic()
this is dc2Derived::~Derived()//在一个函数体中,先实现的对象后释放。
this is dc2Basic::~Basic()
*
*/

4.派生类构造函数首行的写法:

class Basic
{
public:int m_number;string m_name ;char m_sex;//'m' 'w'Basic(int n ,string name , char s);
};
Basic::Basic(int n,string name ,char s):m_number(n),m_name(name),m_sex(s)
{
//     this->m_name = name;
//     this->m_number = n;
//     this->m_sex = s;
}class Derived:public Basic
{
public:int m_age;string m_addr;Derived(int n,string name,char s,int a, string addr);
};
Derived::Derived(int n,string name,char s,int a, string addr):Basic(n,name,s),m_age(a),m_addr(addr)
{}

5.  operator=不能被继承 or Not的探讨

关于operator=的说法比较有争议,以下面的实验结果为准。

(1) operator= 不能被继承[2](个人认为,拷贝形式的除外,否则不能解释上面代码的打印结果以及下面代码的实验结果)。

//MSDN: All overloaded operators except assignment (operator=) are inherited by derived classes.

[如果非要说不能够继承,那也会调用基类中的拷贝式operator=。]

(2)通过使用“using 某类::operator某运算符”语句,就可以继承基类中的运算符了。[3]

//下面的实验说明 
// 1. 一般的operator=不会被继承。
// 2.通过使用“using 某类::operator某运算符”语句,就可以“继承”基类中的运算符了。而如果没有加上该语句,编译会出错。
// 3.msdn和C++的国际标准《ISO/IEC 14882》都说了operator=不能被继承,但是通过在vs2010中的实验,在派生类没有自定义operator=的情况下,派生了会执行基类中的拷贝式operator=。
// 【对于派生类增加的变量赋值,系统默认给定,具体例子见下面的补充说明】
#include <iostream> using namespace std ;class A1 { public:int operator=(int a){return 8;}int operator+(int a){return 9;}int operator=(A1 &a){cout<<"operator=(A1 &a)"<<endl;return 0;} };class B1 : public A1 { public:int operator-(int a){return 7;}#if 1using A1::operator= ; #endif};void test_common() {B1 v;cout << (v + 2) << endl; // OK, print 9cout << (v - 2) << endl; // OK, print 7 cout << (v = 2) << endl; // 如果class B1加了 using A1::operator= ; ,强行“继承”了A1的operator=,则结果为8.// 否则: error C2679: 二进制“=”: 没有找到接受“int”类型的右操作数的运算符(或没有可接受的转换)。 }void test_copy() {B1 v2;B1 v3;v2 = v3 ;//打印效果: operator=(A1 &a)//并且拷贝性质的operator=,从效果上看,能够被继承。//拷贝性质的operator=,如果基类未对其显式地定义,始终还是能被编译器隐式的定义。 } int main() { test_common();test_copy();while(1);return 0; }

关于operator是否继承的问题,下面补充一下:

//下面的实验说明 
// 1. 一般的operator=不会被继承。
// 2.通过使用“using 某类::operator某运算符”语句,就可以“继承”基类中的运算符了。而如果没有加上该语句,编译会出错。
// 3.msdn和C++的国际标准《ISO/IEC 14882》都说了operator=不能被继承,
// 但是通过在vs2010中的实验说明:虽然说不能够继承,但是也会调用执行基类中的拷贝式operator=。
// 4.那么执行了基类的operator=,但是基类operator=没有办法对派生类增加的成员变量赋值,剩下的操作就由系统默认给定(按对象的内存地址依次复制)。
//   
#include <iostream>
using namespace std ;
/
class A1
{
public:int operator=(int a){return a;}A1& operator=(const A1 &a);A1(int val);int GetVal();
private:int m_x;
};A1::A1(int val):m_x(val)
{}int A1::GetVal()
{return this->m_x;
}A1& A1::operator=(const A1 &a) 
{cout<<"operator=(A1 &a)"<<endl;this->m_x = a.m_x *10 ;//注意*10是为了看效果return *this;
}
/
class B:public  A1
{    
private:int m_b;
public:B(int vala,int valb);int GetValB(){return m_b;}
};B::B(int vala,int valb):A1(vala),m_b(valb)
{}
/////
void test_inheritance()
{B  v(11,44);cout<<"get value:"<<v.GetVal()<<endl;//11
B v2(22,33);cout<<"get value:"<<v2.GetVal()<<endl;//22cout<<"get valueB:"<<v2.GetValB()<<endl;//33
v2 = v  ; // operator=(A1 &a) cout<<"get value:"<<v2.GetVal()<<endl;// 110   执行了基类的operator=cout<<"get valueB:"<<v2.GetValB()<<endl;// 44  这里是系统默认生产的。// 打印operator=(A1 &a) 说明给派生类赋值时,执行了 基类operator= 。// 虽然执行了基类的operator=,但是基类operator=没有办法对派生类增加的成员变量赋值,剩下的操作就由系统默认给定(按对象的内存地址依次复制)。// [基类operator=为什么在这里会执行,是不是和构造函数的相同,必然会执行呢?答案是否定的,当B自定义了operator=之后,不会执行基类中的operator=。]
}
int main()
{        test_inheritance();while(1);return 0;
}

参考:

1.构造与析构函数与 operator=不能被继承
  http://www.cnblogs.com/findumars/p/3695340.html

2.为什么C++赋值运算符重载函数不能被继承?
  http://www.eetop.cn/blog/html/11/317611-14436.html

3.C++重载运算符的继承

http://blog.csdn.net/raodotcong/article/details/5501181

转载于:https://www.cnblogs.com/mylinux/p/4094808.html

相关文章:

json转换模型利器--JSONExport

JSONExport 从json 到 Model &#xff0c;如此的方便 swift oc java 全部支持

亚马逊ses如何发qq_使用Amazon SES发送电子邮件

亚马逊ses如何发qqby Kangze Huang黄康泽 使用Amazon SES发送电子邮件 (Sending emails with Amazon SES) 完整的AWS Web样板-教程3 (The Complete AWS Web Boilerplate — Tutorial 3) 目录 (Table of Contents) Part 0: Introduction to the Complete AWS Web Boilerplate第…

源码-0205-02--聊天布局

还真是失败&#xff0c;搞了两天遇到了布局cell高度总是出差的问题&#xff0c;cell height不是高很多很多&#xff0c;就是就是矮到没有的情况。。。。糟糕透顶待解救&#xff5e; 聊天布局 // // XMGChatingViewController.m // 07-聊天布局 #import "XMGChatingViewC…

js实现页面跳转的几种方式

第一种&#xff1a;<script language"javascript" type"text/javascript"> window.location.href"login.jsp?backurl"window.location.href; </script>第二种&#xff1a; <script language"javascript&q…

Mac 升级系统 pod 命令无效

mac 升级完最新的系统之后 使用pod 命令之后无效报错 -bash: /usr/local/bin/pod: /System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/bin/ruby: bad interpreter: No such file or directory 解决方案 sudo gem install -n /usr/local/bin cocoapods

node seneca_使用Node.js和Seneca编写国际象棋微服务,第1部分

node seneca(This is Part 1 of a three-part series [Part 2, Part 3])(这是一个由三部分组成的系列文章的第1部分[ 第2 部分 &#xff0c; 第3部分 ]) I’ve begun wrapping my head around microservices. Up to this time I regarded it as a scalability pattern and ove…

Ubuntu中基于QT的系统网线连接状态的实时监视

1.必要准备 需包&#xff1a; #include <QNetworkInterface> 2.实现获取当前的网线连接状态 以下是自己在网络上搜到的一个解决方法&#xff0c;且没有加入iface.flags().testFlag(QNetworkInterface::IsRunning) 这一逻辑判断&#xff0c;经测试实时性极不可靠&#xff…

iOS 开发者账号 到期续费问题

https://blog.csdn.net/liruiqing520/article/details/104043221

[转载]Using ngOptions In AngularJS

http://odetocode.com/blogs/scott/archive/2013/06/19/using-ngoptions-in-angularjs.aspx?utm_sourcetuicool转载于:https://www.cnblogs.com/Benoly/p/4097213.html

graphql_GraphQL的稳步上升

graphqlToday GitHub announced that the next version of their API will use a new technology developed by Facebook called GraphQL.今天&#xff0c;GitHub宣布其API的下一版本将使用Facebook开发的一项名为GraphQL的新技术。 GraphQL may eventually come to replace t…

转: windows系统下mysql出现Error 1045(28000) Access Denied for user 'root'@'localhost'

windows系统下mysql出现Error 1045(28000) Access Denied for user rootlocalhost 转自 http://zxy5241.spaces.live.com/blog/cns!7682A3008CFA2BB0!361.entry 在windows操作系统安装MySQL数据库&#xff0c;碰到Error 1045(28000) Access Denied for user rootlocalhost 错误…

正则表达式的字符、说明和其简单应用示例

字符和其含义 字符       含义 \         转义字符&#xff0c;将一个具有特殊功能的字符转义为一个普通的字符 ^        匹配字符串的开始位置 $        匹配字符串的结束位置 *        匹配前面的0次或多次的子表达式        …

iOS 设置UILabel 的行间距

// // UILabelLineSpace.h//#import <UIKit/UIKit.h>NS_ASSUME_NONNULL_BEGINinterface UILabel (LineSpace)/**设置文本,并指定行间距param text 文本内容param lineSpacing 行间距*/ -(void)setText:(NSString*)text lineSpacing:(CGFloat)lineSpacing;endNS_ASSUME_N…

倦怠和枯燥_启动倦怠

倦怠和枯燥by Elie Steinbock埃莉斯坦博克(Elie Steinbock) 启动倦怠 (Start-up Burnout) Shabbat is the seventh day of the week. It starts on Friday night and ends on the following evening, Saturday. (A day starts in the evening for the Jews.) It’s also the J…

客户端处理包方法

不同包客户端的处理方法 对于那种事件类型的 连接上了&#xff0c;连接失败了&#xff0c;断开连接了 bool NGP::OnConnected() {std::lock_guard<std::mutex> lock(m_PktMutex);//加锁是因为runonce应该是另一个线程m_queFunctions.push(std::bind(&NGP::Connect2Se…

0011_练习题d1

__author__ qq593 #!/usr/bin/env python #-*- coding:utf-8 -*- #使用while循环输入1 2 3 4 5 6 8 9 10 a1 while True:print(a)if(a10):breakif (a7):a1continuea1 __author__ qq593 #!/usr/bin/env python #-*- coding:utf-8 -*- #求1-100所有数的和 a1 sum00 while(a<…

iOS 仿微信灵活添加标签

iOS 仿微信灵活添加标签 原作者的github 地址 喜欢的点赞 https://github.com/DreamFlyingCow/TTTags 效果如下&#xff0c;iOS 13 访问私有属性 会崩溃&#xff0c;自己修改一下即可 TTTagView.m 文件修改如下 我的备份&#xff1a;https://github.com/AlexanderYeah/TTTa…

css 倒三角_倒三角结构:如何管理大型CSS项目

css 倒三角by Luuk GruijsLuuk Gruijs着 倒三角结构&#xff1a;如何管理大型CSS项目 (The Inverted Triangle Architecture: how to manage large CSS Projects) You’re assigned a small task to fix some little styling issues here and there. You’ve found the correc…

列举一些常见的系统系能瓶颈 Common Bottlenecks

http://www.nowamagic.net/librarys/veda/detail/2408在 Zen And The Art Of Scaling - A Koan And Epigram Approach 一文中&#xff0c; Russell Sullivan 提出一个很有趣的设想&#xff1a;一共有20种经典的瓶颈。这听起来就像只有20种基本的故事情节&#xff08;20 basic s…

Zeal 离线API文档浏览器

zeal是一个windows上的开源的离线文档浏览工具&#xff0c;基于docset格式&#xff0c;可以兼容全部dash的文档。zeal没有代码片段管理的功能&#xff0c;只提供文档浏览功能&#xff0c;不过windows下的用户可算是有的用了。dash目前只提供mac上的版本&#xff0c;作者说有往w…

iOS scrollToItemAtIndexPath 无效的解决方案

在UITableview中放置的UICollectionView,然后设置滚动没有效果scrollToItemAtIndexPath - (void)layoutSubviews {[self.collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForRow:self.selectedIdx inSection:0] atScrollPosition:UICollectionViewScrollPositio…

机器学习编程语言_我应该选择哪种编程语言? 我应该专注于前端吗? 后端? 机器学习?...

机器学习编程语言by Preethi Kasireddy通过Preethi Kasireddy 我应该选择哪种编程语言&#xff1f; 我应该专注于前端吗&#xff1f; 后端&#xff1f; 机器学习&#xff1f; (What programming language should I pick? Should I focus on front-end? Back-end? Machine l…

spdlog源码阅读 (1): sinks

0. spdlog简单介绍 spdlog 是一个快速的 C 日志库&#xff0c;只包含头文件&#xff0c;兼容 C11。项目地址 特性: 非常快只包含头文件无需依赖第三方库支持跨平台 - Linux / Windows on 32/64 bits支持多线程可对日志文件进行循环输出可每日生成日志文件支持控制台日志输出可选…

什么样的程序员才算成熟? 让程序员认清自己的所处的阶段

http://www.nowamagic.net/librarys/veda/detail/1450程序员在经历了若干年编程工作之后&#xff0c;很想知道自己水平到底如何&#xff1f;自己是否已经成为成熟的程序员&#xff1f;虽然程序员会对自己有一个自我评价&#xff0c;但是&#xff0c;自己的评价和社会的评价、专…

iOS访问系统日历 添加提醒事件

1 添加隐私请求提示 Privacy - Calendars Usage Description 2 代码 #import <EventKit/EventKit.h> // 添加提醒事件 - (void)addEventWithTimeStr:(NSString *)timeStr title:(NSString *)title planId:(NSString *)planId {EKEventStore *store [[EKEventStore al…

数据分析从头学_数据新闻学入门指南:让我们从头开始构建故事

数据分析从头学by Mina Demian由Mina Demian 数据新闻学入门指南&#xff1a;让我们从头开始构建故事 (A Beginner’s Guide to Data Journalism: Let’s Build a Story From Scratch) This is an introductory guide on how to produce the beginnings of a piece of data jo…

Comparator 和 Comparable

Comparator 和 Comparable 比较 Comparable是排序接口&#xff1b;若一个类实现了Comparable接口&#xff0c;就意味着“该类支持排序”。而Comparator是比较器&#xff1b;我们若需要控制某个类的次序&#xff0c;可以建立一个“该类的比较器”来进行排序。 我们不难发现&…

朴素贝叶斯算法的python实现

朴素贝叶斯 算法优缺点 优点&#xff1a;在数据较少的情况下依然有效&#xff0c;可以处理多类别问题 缺点&#xff1a;对输入数据的准备方式敏感 适用数据类型&#xff1a;标称型数据 算法思想&#xff1a; 朴素贝叶斯比如我们想判断一个邮件是不是垃圾邮件&#xff0c;那么…

iOS 加载本地和网络gif 图片类扩展

https://github.com/AlexanderYeah/GifKuoZhan [self.meiXueImgView showGifImageWithData:[NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:"美" ofType:"gif"]]];

arkit与现实世界距离比_如何使用ARKit和Pusher构建实时增强现实测量应用程序

arkit与现实世界距离比by Esteban Herrera由Esteban Herrera 如何使用ARKit和Pusher构建实时增强现实测量应用程序 (How to Build a Real-Time Augmented Reality Measuring App with ARKit and Pusher) Augmented reality (AR) is all about modifying our perception of the…