透彻深入C++ ——类篇

1.类就是一个概念的具体实现,是一种内部类型没有的概念的体现。

2.struct在C++中也是一种类,其也可以将函数声明在struct里,作为其成员。然后在声明函数的时候,就要用结构名限定其函数名。

3.新引入的概念class是真正的类声明,class默认的成员变量是私有的,public和private标号将声明分为两个部分,后者是只供成员函数使用的私有成员,前者是可在成员函数之外使用的部分,而struct默认都是公有的,也可以使用private和public声明权限。也可以多次使用public和private标号。

4.构造函数:一定要注意,在C++里不像java有变量的声明,而不是真正的实例。C++中的变量声明就是实例的声明,对于不显式设置五参数构造函数的类,是不能够直接声明一个实例而不初始化的,因为初始化的实质在C++中就是构造函数的调用。

Date today=new Date(1,2,3);//Java
Date today(1,2,3);//C++等价形式
Date today=Date(1,2,3)//C++等价形式

Date today=new Date(1,2,3)//C++表示声明一个动态实例的意思,与java的含义不同。

Date today;//C++表示使用today()构造一个实例,必须有today()的定义才成立
Date today;//Jave表示声明一个变量而没有实例化。

java构造函数如果不写,就是不会对任何内部变量初始化,因为如果不初始化,在java里就只是一个变量,而不是实例。
对于C++构造函数,可以自己写默认函数,也不写,但是不写的话会对内部类型不做初始化操作,但会对类类型调用其初始化函数,按理说都应该初始化才是正确思路,但是C中Struct是不会自动初始化的,所以这里为了兼容,一样不初始化内部类型。
对于包含const和引用的,必须显式得提供默认构造函数。
C++和java一样,想用默认构造函数,要不一个构造函数都不写,要不就必须自己写默认构造函数。

5.静态成员static :与静态变量意义相同,其表示在所有类的实例中保持唯一一份副本。而且这里还对static成员提供了一中特殊机制,就是可以使用类名进行限定直接访问该成员。注意static同样遵守访问权限。

6.复制:类(class和struct)是可以直接使用=直接的,而数组只能依次复制(虽然其实类只是比较复杂的简单类型。。。。,没什么可比性)。无论哪种类型,其实最根本的复制基础都是
* void memcpy(void *dst, void *src, size_t size);
需要调用#include < cstring>

类的复制也只是底层调用该函数而已。该函数就是连续空间的复制,同样适用于数组。

7.const成员函数:

void year() const{
  return  y;
}

这里的const是用在函数上,而且是用在函数参数表之后,表达的也还是不能修改的意思,但是是说函数不能修改类的状态,即不能该修改所有成员。与函数的参数设置为const不同在于,后者约束的是在对输入的参数不能修改,而前者是不能修改所在类的变量。与类声明成const的关系在于:类声明成const之后,表示不能修改该类,也就不能调用那些非const函数,即const对象只能调用const函数,而对非const对象来说,所有函数都没限制。

8.自引用this:this是对实例对象的一个指针,会根据调用的对象自动分配,所以return *this就是返回对象自身,如果返回值类型是引用&,得到的就是该实例,否则就是就是一个新的副本,这两种机制结合在一起的话,就可以形成一种串接函数

date.addyear(1).addmonth(1).addday(1);

const_cast的一个用处在这里会体现,就是会

Date* h=const_cast<Date*> (this);//将指向自身的const指针(如果是一个const 成员函数里,this的类型是const X*)强转为一个普通指针,这时用新指针是可以在const成员函数里修改状态的,这就是消除了const逻辑上的常量性。从物理上修改了其状态。

9.mutable关键词:可变的声明就是用来修改const函数不能修改任何成员变量的。所以mutable与const相当于两种相反的定义。
这种想法的一个简单处理有,const成员函数对于指针来说,不能修改其指向,而可以修改指向空间的修改,与传统的const不同,即是T * const p而不是const T* p;

10.并不是所有使用一个类的函数都要写进这个类,只要不需要直接修改相关的内部变量,只是将该类型作为参数或者返回值,完全可以写在类外,但一般会和该类放在同一个名字空间,如一般类的声明和其他使用函数的声明可以在同一个头文件中。这样使用 该类也会附带可以使用这些函数。

11.重载运算符:对自定义类,如果想要使用一些简单的运算符,是必须要重定义的,否则根本没有意义。

//比较运算符
bool operator!=(Name n,Name m);

//自增/减/+=/-=等自修改运算符
Name& operator++(Name& n);//注意输入和输出的都是引用
Name& operator+=(Name& n,int i);//第一个参数就是自身

//+/-运算 
Name operator+(Name n,int i);//输入输出都是副本,所以尽量用自修改的运算符

//<</>>标准输入输出运算符
ostream& operator<<(ostream& o,Name d);//注意返回的是输出流的引用,所以可以串接输出,并且传入的是副本
istream& operator>>(istream& i,Name& d);//注意传入的是引用,因为需要修改

12.析构函数(~函数名);对一个对象占用资源的处理。像局部变量离开作用域和delete删除一个对象的时候,会调用其析构函数,析构函数是对自身占用的资源的释放,是对只有自己知道,编译器无法自动知道的内容的释放。

~Name(){delete [] p;}

对象(构造及销毁)

1.局部变量:执行到时构造,并按序析构,后构造的先析构。
注意在析构和构造函数下的=复制操作,可能失效。

2.自由存储:new建立的对象。注意删除两次同一自由存储的对象,很有可能有运行时错误。

3.类对象的构造:总是先对类的成员按声明顺序进行初始化。如果成员是基本类型,就会不做初始化;如果是一个类,就会调用其构造函数;这时又分为是否为该类指定一个初始式,即形如

Name name;
Age age;
int sex;
student(int i,Name& n,Age a):sex(i),age(a),name(n)
{
}

如果指定了形如上面的这样的初始式,就可以在该成员构造的时候使用对应构造式,否则就使用默认构造式。无论是哪种,就又是一个类对象的构造,和本条目讨论的一致。
所有成员都初始化完之后,才会调用构造函数,根据传入的参数,和内部的语句对成员进行赋值,而非初始化。

总结:类对象的初始化,注意以下的要点:
(1)构造(初始化)和构造函数不是一回事:构造包括成员的初始化和构造函数的调用;
(2)成员的构造先于构造函数的调用,会按声明顺序依次初始化,
初始化的类型分为以下几种:1.有初始式(即把构造函数的参数或者其他常量值作为自身构造函数的参数)的,即有显性初始化方式的。2.没有初始式的基本类型,不会做初始化,和C中的struct一样。3没有初始式的类类型,会初始化,相当于调用默认构造函数。4.在声明的时候用表达式直接初始化的。
(3)首先对类对象自身会有是否有指定的带参数的构造函数(或者显式地调用默认的构造函数,即不带参数的构造函数)。如果没指定(即形如Date date;),就会调用默认的构造函数。默认构造函数又分为两种,一种是自己提供的可能带语句的构造函数,一种是系统生成的空的构造函数。
(4)注意const类型和&类型,该类型必须初始化。
(5)注意在构造函数里的语句就是赋值了,和初始化不同,不是说后来在构造语句里赋了值,前面的成员变量就可以不初始化。
不初始化的只有非const和非&的基本类型,类类型也是必须初始化的。

4.复制赋值=:默认的=是会对其成员一个一个对应复制赋值,但是如果有&类型,就执行的是引用同一个对象的操作,而不是我们希望的副本,所以要注意。有必要时自己定义=操作符

5.类类型数组:使用数组的类,必须满足可以提供默认构造函数。
可以在默认的构造函数里设计一些东西,来实现其构造时的不同:

//构造的函数里输入
class buffer{
 public :
     string abuffer;
     buffer(){
         cin>>abuffer;
     }
};
int main()
{

    buffer buffers[5];
    cout<<buffers[1].abuffer;
    return 0;
}

6.局部静态变量:析构时也是按构造的顺序进行。
7.非局部变量:包括全局空间,名字空间里,所有类的static变量,都会在main()函数前完成初始化,其析构也是在main函数返回之后。其构造的顺序是按照定义的顺序,而不是声明的顺序。
8.临时对象:(很复杂的东西。。。)常作为算数表达式出现
注意:临时对象作为const 引用对象或命名对象的初始式使可以的。但是不能做非const引用的初始化。临时对象是作为一种不可修改的结果来看的。所以这里主要是&的属性,其只能只想可修改的变量,且必须被初始化。
补:const和&都是必须被初始化的。

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值