C++——类和对象

类的定义:
类定义是以关键字 class 开头,后跟类的名称。类的主体是包含在一对花括号中。类定义后必须跟着一个分号或一个声明列表。例如,我们使用关键字 class 定义 Box 数据类型,如下所示:
类要声明在main函数前面

class Box {
public: double length; // 盒子的长度
double breadth; // 盒子的宽度
double height; // 盒子的高度
};

Public 成员可以通过(.)来访问;
私有的成员(private)和受保护的(protected)成员不能使用直接成员访问运算符 (.) 来直接访问。
访问修饰符在类内部不分先后顺序
但是我们习惯先写public再写private或者protected

成员函数:(函数定义之后必须实现)
类的成员函数是指那些把定义和原型写在类定义内部的函数,就像类定义中的其他变量一样。类的成员函数是类的一个成员,它可以操作类的任意对象,可以访问对象中的所有成员。成员函数是内联的。也可以在类的外部定义成员函数,但外部定义的函数是外链的。

类的成员函数和构造函数在类中进行声明过后,既可以在类中定义,也可以放在类的外面进行定义
在类外定义只需要在函数类型后面加上 classname::

构造函数:(有参、无参)
每个类都分别定义了它的对象被初始化的方式,类通过一个或几个特殊的成员函数来控制其对象的初始化过程,这些函数叫构造函数。构造函数的任务是初始化类对象的数据成员,无论何时只要类的对象被创建,都会执行构造函数。

构造函数带有参数时。在创建对象时就会给对象赋初始值

定义:
classname::classname(parameter list)
{
}

1、构造函数的名字和类名相同、无返回类型。有一个(可能为空的)参数列表和一个(可能为空的)函数体。

2、类可以包含多个构造函数,和其他重载函数差不多,不同的构造函数之间必须在参数数量或参数类型上有所区别。

3、不同于其他成员函数,构造函数不能被声明成const的。当我们创建类的一个const对象时,直到构造函数完成初始化过程,对象才能真正取得其“常量”属性。因此,构造函数在const对象的构造过程中可以向其写值。

4、与其他成员函数相同的是,构造函数在类外定义时也需要明确指出是哪个类。

5通常情况下,我们将构造函数声明为public的,可以供外部调用。然而有时候我们会将构造函数声明为private或protected的:
(1)如果类的作者不希望用户直接构造一个类对象,着只是希望用户构造这个类的子类,那么就可以将构造函数声明为protected,而将该类的子类声明为public。(2)如果将构造函数声明为private,那只有这个类的成员函数才能构造这个类的对象。

默认构造函数(缺省构造函数)
默认构造函数没有参数,即在实例化对象时不需要给定初始值,这时所调用的构造函数为默认构造函数。默认构造函数的初始化规则:
(1)如果存在类内初始值,则用它来初始化成员。
(2)默认初始化。

拷贝构造函数
类里面有一个默认的拷贝构造函数,但是我们也可以重写拷贝构造,以此来覆盖默认的拷贝构造。
默认形式:
CExample(const CExample & cexample) //默认构造函数
{
}
重写:
CExample(const CExample & cexample) //拷贝构造函数
{
a=cexample.a+100;
}
注意:我们用const 修饰来保护我们传递的引用

什么时候会调用到拷贝构造函数 ?
1.)当函数的参数为类的对象时 (多态):
void func(CExample c)
{
cout<<“g_func”<<endl;
}
2.)函数的返回值是类的对象 :
CExample func()
{
CExample cexample(0);
return cexample;
}
3.)对象需要通过另外一个对象进行初始化:
CExample cexample_1(n); //创建一个普通的对象
CExample cexample_2=cexample_1; //赋值

This指针
this 指针是一个const 指针,它指向当前对象,通过它可以访问当前对象的所有成员。
this 指针只能作用在类的内部,只有在对象被创建以后才会给 this 赋值,并且这个赋值的过程是隐式的,不需要用户干预,用户不能显式地给 this 赋值。
this 实际上是成员函数的一个形参,在调用成员函数时将对象的地址作为实参传递给 this。这个过程是由编译器隐式实现

静态成员变量(整个类的所有成员共享的变量)static
1)一个类中可以有一个或多个静态成员变量,所有的对象都共享这些静态成员变量,都可以引用它。
2)类的 static 成员变量和普通 static 变量一样,都在内存分区中的全局数据区分配内存,到程序结束时才释放。这就意味着,static 成员变量不随对象的创建而分配内存,也不随对象的销毁而释放内存。而普通成员变量在对象创建时分配内存,在对象销毁时释放内存。
3) 静态成员变量必须初始化(否则整个程序都编译不通过),而且只能在类体外进行,并且只能在main函数之前进行,不能在main函数使用的时候才进行。

静态成员函数
和静态数据成员一样,静态成员函数是类的一部分,而不是对象的一部分。允许使用 类名::func() 这种形式来调用静态成员函数,同样允许使用类的对象名来调用静态成员函数。
类中的普通成员函数可以访问所有成员(包括静态成员变量和静态成员函数);然而静态成员函数只能访问静态成员。
编译器在编译一个普通成员函数时,会隐式地增加一个形参 this,并把当前对象的地址赋值给 this,而静态成员函数可以通过类来直接调用,编译器不会为它增加形参 this。因此静态成员函数不能调用本类的其他非静态成员。
在定义静态成员函数的时候不用加static ,只需要在声明的时候加上static即可。例:
声明:static void test();
定义:void Student::test(){………….}
可以直接在函数体中使用: Student::test(10);
一般情况下我们在静态成员函数中只能使用静态数据,而不能使用非静态数据
(除非使用对象名.非静态成员,(此处要在函数中创建一个本类对象))
静态成员函数不能调用静态成员变量,也不能调用其他的静态成员函数

经过测试发现:
如果只是单纯初始化并且调用了类中的 静态成员(变量或函数),不会执行该类的构造函数和析构函数。
但是,如果调用静态成员函数时(函数内部有静态成员变量),没有初始化静态成员变量时,编译会通不过。

const成员变量
const 成员变量的用法和普通 const 变量的用法相似,只需要在声明时加上 const 关键字。初始化 const 成员变量只有一种方法,就是通过构造函数的初始化列表
const成员函数(常成员函数)
const 成员函数可以使用类中的所有成员变量,但是不能修改它们的值,这种措施主要还是为了保护数据而设置的。const 成员函数也是成员函数。
我们只要在声明函数的时候在结尾加上 const 修饰,在函数定义的时候也要加上 const。
我们通常将 get() 函数 设置为常成员函数。
函数开头的 const 用来修饰函数的返回值,表示返回值是 const 类型,也就是不能被修改,例如const char * getname(){}
函数头部的结尾加上 const 表示常成员函数,这种函数只能读取成员变量的值,而不能修改成员变量的值,例如char * getname() const{}

const对象
const 也可以用来修饰对象,称为常对象。一旦将对象定义为常对象之后,就只能调用类的 const 成员
定义常对象的语法和定义常量的语法类似:
const class object(params);
class const object(params);
当然你也可以定义 const 指针:
const class *p = new class(params);
class const *p = new class(params);
class为类名,object为对象名,params为实参列表,p为指针名。两种方式定义出来的对象都是常对象。

友元、友元函数、友元类
借助友元(friend),可以使得其他类中的成员函数以及全局范围内的函数访问当前类的 private 成员。
类中的友元函数友元函数可以访问当前类中的所有public、protected、private 属性的成员。
在当前类以外定义的、不属于当前类的函数(也可以在类中声明),在函数名前面加 friend 关键字,这样就构成了友元函数。友元函数可以是不属于任何类的非成员函数,也可以是其他类的成员函数。

注意:若A类为B类的友元类,则A类的所有成员函数都是B类的友元函数,都可以访问B类的私有和保护成员。

需要指明三点:1.友元关系是不能传递的 2.友元关系是单向的 3.友元关系是不被继承的。
一般情况下,类必须在正式声明之后才能使用;但是某些情况下(如上例所示),只要做好提前声明,也可以先使用。

再提struct
C++中保留了C的 struct 关键字,并且加以扩充。在C语言中,struct 只能包含成员变量,不能包含成员函数。而在C++中,struct 类似于 class,既可以包含成员变量,又可以包含成员函数。
C++中的 struct 和 class 基本是通用的,唯有几个细节不同:
使用 class 时,类中的成员默认都是 private 属性的;而使用 struct 时,结构体中的成员默认都是 public 属性的。
class 继承默认是 private 继承,而 struct 继承默认是 public 继承。
class 可以使用模板,而 struct 不能。
在编写C++代码时,强烈建议使用 class 来定义类,而使用 struct 来定义结构体,这样做语义更加明确。

小结:
1. 类的成员有成员变量和成员函数两种。

2. 成员函数之间可以互相调用,成员函数内部可以访问成员变量。

3. 私有成员只能在类的成员函数内部访问。默认情况下,class 类的成员是私有的,struct 类的成员是公有的。

4. 可以用“对象名.成员名”、“引用名.成员名”、“对象指针->成员名”的方法访问对象的成员变量或调用成员函数。成员函数被调用时,可以用上述三种方法指定函数是作用在哪个对象上的。

5. 对象所占用的存储空间的大小等于各成员变量所占用的存储空间的大小之和(如果不考虑成员变量对齐问题的话)。

6. 定义类时,如果一个构造函数都不写,则编译器自动生成默认(无参)构造函数和复制构造函数。如果编写了构造函数,则编译器不自动生成默认构造函数。一个类不一定会有默认构造函数,但一定会有复制构造函数。

7. 任何生成对象的语句都要说明对象是用哪个构造函数初始化的。即便定义对象数组,也要对数组中的每个元素如何初始化进行说明。如果不说明,则编译器认为对象是用默认构造函数或参数全部可以省略的构造函数初始化。在这种情况下,如果类没有默认构造函数或参数全部可以省略的构造函数,则编译出错。

8. 对象在消亡时会调用析构函数。

9. 每个对象有各自的一份普通成员变量,但是静态成员变量只有一份,被所有对象所共享。静态成员函数不具体作用于某个对象。即便对象不存在,也可以访问类的静态成员。静态成员函数内部不能访问非静态成员变量,也不能调用非静态成员函数。

10. 常量对象上面不能执行非常量成员函数,只能执行常量成员函数。

11. 包含成员对象的类叫封闭类。任何能够生成封闭类对象的语句,都要说明对象中包含的成员对象是如何初始化的。如果不说明,则编译器认为成员对象是用默认构造函数或参数全部可以省略的构造函数初始化。

12. 在封闭类的构造函数的初始化列表中可以说明成员对象如何初始化。封闭类对象生成时,先执行成员对象的构造函数,再执行自身的构造函数;封闭类对象消亡时,先执行自身的析构函数,再执行成员对象的析构函数。

const 成员和引用成员必须在构造函数的初始化列表中初始化,此后值不可修改。

友元分为友元函数和友元类。友元关系不能传递。

成员函数中出现的 this 指针,就是指向成员函数所作用的对象的指针。因此,静态成员函数内部不能出现 this 指针。成员函数实际上的参数个数比表面上看到的多一个,多出来的参数就是 this 指针。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值