C++中与类有关的注意事项(更新中~~~)
- 关于构造函数的调用次序,见下列代码
#include<iostream>
using namespace std;
class A
{
private:
int x;
public:
A():x(0){ cout << "Construct A----" << x << endl; }
A(int i):x(i){ cout << "Construct A----" << x << endl; }
~A() { cout << "Des A----" << x << endl; }
};
class B
{
private:
int y;
public:
B():y(0){ cout << "Construct B----" << y << endl; }
B(int i):y(i){ cout << "Construct B----" << y << endl; }
~B() { cout << "Des B----" << y << endl; }
};
class C
{
private:
int z;
public:
C(int i):z(i){ cout << "Construct C----" << z << endl; }
~C() { cout << "Des C----" << z << endl; }
};
class D:public B
{
public:
A a0, a4; // l1
B b2, b1; // l2
C c1, c2; // l3 //其构造函数调用次序与这里的顺序有关
D():c2(2), c1(1), a4(4),B(1), b2(3) { cout << "Construct D----5" << endl; } //B(i)调用的是D的基类构造函数,它首先开始
~D(){ cout << "Des D----5" << endl; }
};
int main()
{
D d;
}
当然了,首先调用基类的构造函数是不容置疑的,不管它在哪里,记住即可,不过关于对象成员的构造函数的调用还需注意, 见 L1, L2, L3, 它们的构造函数的调用次序与它们在此的相对次序有关,如类A排在第一行,因此先调用关于它的对象,这里还应再注意一点,尽管先定义了它的对象成员,不过它不会立即调用其默认构造函数,而是去看看你有没有写相应的初始化(注意:这里是指在类里面,而不是指main函数内以及类外函数,对于类外函数应注意,在定义类的同时必须给它附上一定的值,不过这根据需要而定,如果你已经设置了无参构造函数了或者你在类内定义了一些set函数),比如调用完基类构造函数后优先调用a0的构造函数,但初始化列表中并没有它,故调用它的默认构造函数,然后调用a4的构造函数,依此类推,就不难理解编译运行后的结果了。
关于析构函数的调用只需知道它与构造函数的调用刚好对称即可。
针对继承,其构造函数的一般调用顺序为基类构造函数 ---> 成员对象的构造函数 ---> 它自身的构造函数(这里是指初始化列表后大括号内的内容)
- 类的静态成员(static member)必须在类内声明,在类外初始化。
- 类里面的任何成员变量在定义时是不能初始化的,尽管你可以编译过。
- 类的一个对象调用了一次构造函数之后,是不允许再次调用构造函数的。
- 如果一个类是另一个类的友元类,那么该类的友元函数将不能访问另一个类的私有成员。
class Base
{
public:
int x = 0;
protected:
double y = 0;
private:
float z = 0;
friend class Deri;
};
class Deri:public Base
{
protected:
int dx = 1;
public:
friend void f2(Base b);
void f3(Base b){cout << b.x << " " << b.y << " " << b.z << endl; } //在友元类内部可以访问另一个类私有成员
};
void f2(Base b)
{
cout << "======" << endl;
cout << b.x << " " << b.y << " " << b.z<< endl; //error, y和z都无法访问
}
- 类内的函数名不可和数据成员的名称重复。
如
class First1
{
private:
int memi;
double memd;
public:
int memi(){return memi;} //error
double getmemd(){return memd;}
};
- 无论是在类外还是在类内访问私有成员时最好设置一个接口,养成一个习惯。
#include<iostream>
using namespace std;
class First1
{
private:
double memd;
public:
double getmemd(){return memd;}
};
int main()
{
First1 a;
cout << a.getmemd() << endl;
}
- 当该类的对象离开了它的域或者delete表达式应用到一个该类的对象的指针上时,析构函数会自动被调用。
- 看一段代码:
#include<iostream>
using namespace std;
class Data
{
private:
int d;
public:
Data():d(0){}
Data(const int dd):d(dd){}
Data operator+(Data b)
{
Data c = d + b.d;
return c;
/*
int c = d + b.d;
return Data(c); //true,和下面一样
Data c_(c);
return c_; //true
*/
}
friend ostream &operator<<(ostream& os, const Data &b);
};
ostream& operator<<(ostream& os, const Data &b)
{
os << b.d;
return os;
}
int main()
{
Data a, b(1);
cout << a + b << endl;
return 0;
}
- 在使用类模板对象时,必须显示地指定模板实参,否则就会报错。
- 在写类模板时,如何需要用到另一个类模板的私有成员,注意千万不要写成普通的友元形式,那样报错报到你哭,步骤自身感觉比较繁琐,见链接https://blog.csdn.net/lezardfu/article/details/61433246,实在不行在另一个类中写相应的public接口。
关于运算符重载需要注意以下几点:
- 作为类成员的重载函数(以类名作为返回类型),其形参看起来比操作数少一个,因为隐式传递,限定为第一个操作数,举个例子,如下:
T operator + (const Data<T> d) {
return value + d.value;
} /*这是一个类模板内的一个成员函数,注意人家
在使用类对象时显示的指定模板实参了,不要忘了,另外系统隐藏了一个
类对象,一般两个对象中隐藏第一个*/
- 重载>> 和 << 时一般在public处声明(声明时不要忘记它是友元函数),在类外定义,注意它是非成员函数(这其中包括普通函数,友元函数)。但也有例外,比如你写了个类模板,并且你给它写了个运算符重载<<,这时你就不能按照常规做了,要既在类内声明,又在类内定义,同时不要忘记显示指定模板实参。注意:重载<<时写成 “friend ostream& operator<<(ostream &os, const Data<T> &s)”形式,避免出现发现不出来的错。
- 一般将算术操作符定义为非成员函数,如+, - , *, /,不过也可以将它定义成成员函数
friend Complex operator+(Complex a, double b) {return Complex(a.r + b, a.i); /*这里定义成友元函数比较好*/
/*注意:写成这样就不对了*/
//例如
Complex(Complex a, Complex b){} /*如果你想得到a和b相加后的结果,这样写是不对的,因为多了一个*/
/*应写成这样*/
Complex(Complex b)
{
Complex c;
...
return c(...);
}
- 一元运算符(如++,--)因为其位置不同而导致重载形式不同,如
friend X& operator++(X& o); /*相当于++a,自增完后直接返回引用*/
/*或者这样*/ X& operator++(); /*相当于++a,自增完后直接返回引用*/
friend X operator++(X& o, int ); /*相当于a++,自增完后返回一个临时的*/
- 赋值必须返回对*this的引用(如+=, =)
- 下标运算符 [ ] 一般作为类成员函数,中间加上const就更好了。
- 重载类型转化操作符时应注意1.必须定义为类成员函数. 2.不能指定返回类型。 3.必须返回要转换成的类型
class Circle
{
private:
double x, y, r;
public:
Circle(double a, double b, double c):x(a), y(b), r(c){}
operator int(){return int(r);}
};
C++中与类有关的注意事项(更新中~~~)的更多相关文章
- C++中的类所占内存空间+继承中的成员访问控制
C++学习之继承中的成员访问控制 C++中的类所占内存空间总结
- html2canvas - 项目中遇到的那些坑点汇总(更新中...)
截图模糊 原理就是讲canvas画布的width和height放大两倍. 后来学习canvas的时候,才了解到这种写法不同于css的宽高设置, 因为css里的只是展示画布显示的大小,不像这样是c ...
- C# 中一些类关系的判定方法 C#中关于增强类功能的几种方式 Asp.Net Core 轻松学-多线程之取消令牌
1. IsAssignableFrom实例方法 判断一个类或者接口是否继承自另一个指定的类或者接口. public interface IAnimal { } public interface ID ...
- iOS中容易混淆的知识点(持续更新中)
1.成员变量和属性的区别 @interface Person : NSObject { NSString *_sex; } @property (nonatomic, copy) NSString * ...
- Java中的那些名词术语(不断更新中)
在工作和学习中,总会遇到各种术语.岁月不饶人,记忆力越来越下降.在这里记录下那些曾经关注过学习过的东西. POJO: Plain Old Java Object DI: Dependency Inje ...
- dubbo初认知(dubbo和springCloud关系,在微服务架构中的作用等)(持续更新中)
一:dubbo是什么? dobbuo是阿里开源的一个高性能优秀的服务框架, 可通过高性能的 RPC 实现服务的输出和输入功能,使得应用可以和 高性能的rpc实现输入和输出的功能,可以了 Spring ...
- OI中一些常见实用的套路【更新中】
数据结构 在维护树上路径时,如果只是点的独立的加减,可以考虑用括号序来维护(拆成两部分) 需要求树上很多路径中k近/距离和 一类,考虑点分治/在点分树上解决. 子树求和可以转化为DFS序上区间求和 树 ...
- 工作中常用的Linux命令(不断更新中)
最近工作中用到linux命令,简单总结如下: 1. pwd 查看当前所在的文件路径 2. cd 切换目录 cd .. 切换到上一级目录 3. ls 列出当前文件路径下的所有文件和文件夹 4. ll 是 ...
- CEUtils---我在Unity中使用的一些小类库(不断更新中)
项目地址: http://git.oschina.net/eran/CEUtils
随机推荐
- 【环境搭建与软件安装】windows系统基于Anaconda安装tensorflow-gpu
https://github.com/tensorflow/tensorflow/issues/21832 原来是tensorflow-gpu-1.10.0,准备改为1.9.0试试,同样的问题: 应该 ...
- [LeetCode] 49. Group Anagrams 分组变位词
Given an array of strings, group anagrams together. For example, given: ["eat", "tea& ...
- 使用命令行操控vmware--安装
在虚拟化出现之前,服务器的使用率很低,一般只有15%-20%,其余的资源处于闲置状态,但vmware出现之后,首先,可以充分的利用资源,从而达到节约成本的目的,其次,使得虚机便于维护.一般小型公司使用 ...
- 关于Excel 2016 总要点击两次才能打开的解决方法
1.快捷键:win+r,输入:regedit2.定位到如下项目“HKEY_CLASSES_ROOT\Excel.Sheet.12\shell\Open\command”:3.编辑原有的内容,在最后添加 ...
- 使用Delphi开发linux应用
对于很多喜欢使用delphi做开发的人都希望delphi能够支持linux平台的开发,终于在delphi10.2版本中,delphi开始支持linux平台的开发了.在这里写一下Linux开发环境的配置 ...
- [转帖]中兴GoldenDB数据库开始了第一轮中信银行核心业务系统迁移落地
中兴GoldenDB数据库开始了第一轮中信银行核心业务系统迁移落地 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https:// ...
- 删除List集合中的元素你碰到过这样的陷阱吗?
删除List的三种方式: (1) 普通遍历 : @Test public void testList(){ ArrayList<String> list = new ArrayList&l ...
- C语言之指针在printf语句里面的使用规范
*** 一级指针的使用规则探索 *** #include<stdio.h> #include<stdlib.h> void main() { char *p; p = &quo ...
- AttributeError: 'sys.flags' object has no attribute 'utf8_mode'
AttributeError: 'sys.flags' object has no attribute 'utf8_mode' pycharm工程的py版本是3.6,结果即使使用py3.7编译后的py ...
- macbook下使用pycharm2019版本配置远程连接服务器
pycharm提供了很方便的与服务器同步代码,并执行的插件.我在配置windows版的pycharm时配置成功,在挪用到mac上则遇到了些许问题,终于是解决了,在此记录配置的过程 目的:pycharm ...