知识点:

1、C++类的定义

   1、class是 C++ 中新增的关键字,专门用来定义类。Student是类的名称;类名的首字母一般大写,以和其他的标识符区分开。{ }内部是类所包含的成员变量和成员函数,它们统称为类的成员(Member);由{ }包围起来的部分有时也称为类体,和函数体的概念类似。public也是 C++ 的新增关键字,它只能用在类的定义中,表示类的成员变量或成员函数具有“公开”的访问权限
注意在类定义的最后有一个分号;,它是类定义的一部分,表示类定义结束了,不能省略。

类只是一个模板(Template),编译后不占用内存空间,所以在定义类时不能对成员变量进行初始化,因为没有地方存储数据。只有在创建对象以后才会给成员变量分配内存,这个时候就可以赋值了。

(1) 类名
     遵循一般的命名规则; 字母,数字和下划线组合,不要以数字开头。
(2) 类成员
     类可以没有成员,也可以定义多个成员。成员可以是数据、函数或类型别名。所有的成员都必须在类的内部声明。
没有成员的类是空类,空类也占用内存!
(3) 构造函数
     构造函数是一个特殊的、与类同名的成员函数,用于给每个数据成员设置适当的初始值。
(4) 成员函数
     成员函数必须在类内部声明,可以在类内部定义,也可以在类外部定义。如果在类内部定义,就默认是内联函数。
 C++中使用关键字  class 来定义类, 其基本形式如下:

class 类名
{
public:
//公共的行为或属性
private:
};
示例:
     定义一个点(Point)类, 具有以下属性和方法:
     ■ 属性: x坐标, y坐标
     ■ 方法: 1.设置x,y的坐标值; 2.输出坐标的信息。
实现代码:
class Point
{
public:
     void setPoint(int x, int y);
     void printPoint();
 
private:
     int xPos;
     int yPos;
};  
     上段代码中定义了一个名为 Point 的类, 具有两个私密属性, int型的xPos和yPos, 分别用来表示x点和y点。
     在方法上, setPoint 用来设置属性, 也就是 xPos 和 yPos 的值; printPoint 用来输出点的信息。    

2、类的对象:

仅声明类并不会对程序的执行产生影响。在运行阶段,对象就是类的化身。要使用类的功能,通常需要类实例化一个对象,并通过对象访问成员方法和属性。
实例化Hu对象与创建其他类型的实例一样。
向为int动态分配内存一样,也可以使用new为Hu对象动态的分配内存。
使用句点运算符访问成员:
在具体实现一个类之前,我们需要先了解一个运算符:作用域解析运算符(::)。该符号的作用是用来标识一个函数所属的类,例如当我们输入Student::average()时。表示我们访问的average()方法属于Student类而不是其他的类。 
但是在一个Student类的内部我们并不需要使用使用作用域解析运算符就能访问average()方法,这是因为在类的内部自身所定义的所有方法对自身来说都是可见的。 
对于一个方法名称来说,Student::average()是方法的函数限定名(全称),而average()方法属于非限定名(简称),当程序对于一个函数来源无异议时(没有重名方法),可以使用简称。

类声明表明,一个对象有着好几个属性,可以使用句点运算符来访问,这个用起来也很方便。
如果有一个指针yu,他指向Hu类的一个实例,则可使用指针运算符(—〉)来访问成员,也可使用间接运算符(*)来获取对象,再使用句点运算符来访问成员:
例如;Hu*yu=new Hu();
(*yu).introduceself();
自己对类名定义的感受就是除了定义数据和函数成员之外,类还可以定义自己的局部类型名字。
使用类型别名有很多好处,它让复杂的类型名字变得简单明了、更容易理解和使用,还有助于自己清楚地知道使用该类型的真实目的。

3.内联函数

     可以分为有三种
(1)直接在类的内部定义
 (2)在类内部声明,加上inline关键字,在类外部定义。
(3)在类内部声明,在类外部定义,同时加上inline关键字。
在创建类的对象之前,必须完整的定义该类,而不只是声明类。类不能具有自身类型的数据成员,但可以包含指向本类的指针和i引用。

4. 析构函数

     构造函数的用途之一是自动获取资源;与之相对的是,析构函数的用途之一是回收资源。除此之外,析构函数可以执行任意类设计者希望在该类对象的使用完毕之后执行的操作。
(1) 何时调用析构函数
撤销(销毁)类对象时会自动调用析构函数。
变量(类对象)在超出作用域时应该自动撤销(销毁)。
动态分配的对象(new A)只有在指向该对象的指针被删除时才撤销(销毁)。
撤销(销毁)一个容器(不管是标准库容器还是内置数组)时,也会运行容器中的类类型元素的析构函数(容器中的元素总是从后往前撤销)。
(2)何时编写显式析构函数
     如果类需要定义析构函数,则它也需要定义赋值操作符和复制构造函数,这个规则常称为三法则:如果类需要析构函数,则需要所有这三个复制控制成员。
(3)合成析构函数
     合成析构函数按对象创建时的逆序撤销每个非 static 成员,因此,它按成员在类中声明次序的逆序撤销成员。
     对于每个类类型的成员,合成析构函数调用该成员的析构函数来撤销对象。
     合成析构函数并不删除指针成员所指向的对象。 所以,如果有指针成员,一定要定义自己的析构函数来删除指针。  析构函数
     构造函数的用途之一是自动获取资源;与之相对的是,析构函数的用途之一是回收资源。除此之外,析构函数可以执行任意类设计者希望在该类对象的使用完毕之后执行的操作。

 5.友元函数

     友元机制允许一个类将对其非公有成员的访问权授予指定的函数或类。
     友元可以出现在类定义的内部的任何地方。
     友元不是授予友元关系的那个类的成员,所以它们不受声明出现部分的访问控制影响。
     建议:将友元声明成组地放在类定义的开始或结尾。

6. static 类成员

static 成员,有全局对象的作用,但又不破坏封装。

1 .static 成员变量

static 数据成员是与类关联的对象,并不与该类的对象相关联。
static 成员遵循正常的公有/私有访问规则。  

2. 使用 static 成员而不是全局对象有三个优点。

(1)  static 成员的名字是在类的作用域中,因此可以避免与其他类的成员或全局对象名字冲突。
(2)  可以实施封装。static 成员可以是私有成员,而全局对象不可以。
(3)  通过阅读程序容易看出 static 成员是与特定类关联的,这种可见性可清晰地显示程序员的意图。 


3. static 成员函数

     在类的内部声明函数时需要添加static关键字,但是在类外部定义函数时就不需要了。
     因为static 成员是类的组成部分但不是任何对象的组成部分,所以有以下几个特点:
1) static 函数没有 this 指针
2) static 成员函数不能被声明为 const (将成员函数声明为 const 就是承诺不会修改该函数所属的对象)
3) static 成员函数也不能被声明为虚函数


4 .static 数据成员 

     static 数据成员可以声明为任意类型,可以是常量、引用、数组、类类型,等等。
     static 数据成员必须在类定义体的外部定义(正好一次),并且应该在定义时进行初始化。
建议:定义在类的源文件中名,即与类的非内联函数的定义同一个文件中。注意,定义时也要带上类类型+"::"
double Account::interestRate = 0.035; 

5 .特殊的静态常量整型成员 

     静态常量整型数据成员可以直接在类的定义体中进行初始化,例如:
static const int period = 30; 
     当然char 可以转换成整形,也是可以的,   static const char bkground = '#';
 

6. 其他

(1)static 数据成员的类型可以是该成员所属的类类型。非 static 成员只能是自身类对象的指针或引用 
class Screen 
{
public:
         // ...
private:
         static Screen src1; // ok
         Screen *src2;       // ok
         Screen src3;        // error
}; 
(2)非 static 数据成员不能用作默认实参,static 数据成员可用作默认实参
class Screen 
{
public:
          Screen& clear(char = bkground);
private:
         static const char bkground = '#';//static const整形变量可以在类内部初始化。
};

题型:

1、实现类成员


现在我们创建一个C++文件student.cpp

//student.cpp -- implementing the Student class
//version 00
#include "stdafx.h"
#include "student.h"

Student::Student(){
}
Student::~Student(){
}
void Student::setChScore(int score){
    Student::ch = score;
}
void Student::setName(std::string n){
    Student::name = n;
}
void Student::setEnScore(int score){
    en = score;
}
void Student::setMathScore(int score){
    math = score;

}


//不需要知道这个方法的具体实现,后面会介绍,本节重点是类与对象
void Student::show(){
    Student::count();
    ios_base::fmtflags orig = cout.setf(ios_base::fixed,ios_base::floatfield);
    std::streamsize prec = cout.precision(1);
    cout<<name<<" 同学的语文成绩为"<<ch<<"分,数学成绩为"<<math<<"分,英语成绩为"<<en<<"分,平均成绩"<<average<<"分"<<endl;
    cout.setf(orig,ios_base::floatfield);
}

注意这个实现的Student::setChScore(int score)中我们在使用ch参数时使用了作用于解析运算符,其实在类的内部我们可以直接使用简称,所以在后续的方法中我们使用了非限定名。

2、创建对象以后,可以使用点号.来访问成员变量和成员函数,这和通过结构体变量来访问它的成员类似,如下所示:

#include <iostream>

using namespace std;
//类通常定义在函数外面
class Student{
public:
    //类包含的变量
    char *name;
    int age;
    float score;
    //类包含的函数
    void say(){
        cout<<name<<"的年龄是"<<age<<",成绩是"<<score<<endl;
    }
};
int main(){
    //创建对象
    Student stu;
    stu.name = "小明";
    stu.age = 15;
    stu.score = 92.5f;
    stu.say();
    return 0;
}
运行结果:
小明的年龄是15,成绩是92.5
stu 是一个对象,占用内存空间,可以对它的成员变量赋值,也可以读取它的成员变量。
类通常定义在函数外面,当然也可以定义在函数内部,不过很少这样使用。

感悟

  首先,学习类更大扩展了我们对于编程的认识,对于解决问题来说更加的方便,更加的灵活,当然现在的我还有还多方面需要加强,比如对于运算符的理解,知道含义之后怎么合理的运用它,他该出现在那个位置,对于我的编程提出来了更高的要求。具体到每一个细节,例如在通过对象指针访问对象和对象成员中(*pt).hour与pt->hour的等价性,还有对于怎样定义指向成员函数的指针变量中void(Time::*p2)()与void Time::*p2()的区别,前者是正确的,而后者是返回值为void类型指针的函数。这些细小的细节或许会造成天大的差别,所以在以后的学习中要不断的注意这些。
  再者,当自己的运算符理解透彻之后,又要求自己在类函数之间的连接性方面不断加强,就像老师说的,在调完一个类后再去调节另一个,这样会使得在程序调节过程中能比较集中的处理一个点,但是怎样使得每个类都能完美的衔接在一起,在以后的学习中还要加强,而怎样提高自己自这方面的能力,我想不仅需要自己多做题,而且还要与同学不断地进行交流沟通,分享大家的想法,以达到共同受益的目的。














猜你喜欢

转载自blog.csdn.net/qq_40349011/article/details/80023436
今日推荐