C++类&对象


文章目录

  • C++类&对象
    • 一、类和对象定义
      • 1.对象
      • 2.类
    • 二、成员变量&成员函数
      • 1.使用类的成员变量和成员函数
      • 2.类成员的可访问范围
      • 3.成员函数可以重载及参数缺省
    • 三、构造函数
      • 1.构造函数概念
      • 2.构造函数定义
      • 3.构造函数生成
      • 4.构造函数作用
      • 5.构造函数示例
    • 四、复制构造函数
      • 1.复制构造函数基本概念
      • 2.复制构造函数起作用的三种情况
      • 3.注意:对象间赋值并不导致复制构造函数被调用
    • 五、类型转换构造函数
      • 1.类型转换构造函数基本概念
      • 2.类型转换构造函数示例
    • 六、析构函数
      • 1.析构函数基本概念
      • 2.析构函数示例
    • 七、this指针
      • 1.this指针的作用
      • 2.this指针和静态成员函数
    • 八、静态成员
      • 1.静态成员基本概念
      • 2.静态成员的访问
      • 3.静态成员注意事项
    • 九、成员对象和封闭类
      • 1.封闭类定义
      • 2.封闭类构造函数和析构函数的执行顺序
      • 3.封闭类实例
      • 4.封闭类的复制构造函数
    • 十、友元
      • 1.友元函数
      • 2.友元类
      • 3.友元类注意事项
    • 十一、常量成员函数
      • 1.常量成员函数基本概念
      • 2.常量成员函数的重载
      • 3.mutable成员变量

一、类和对象定义

1.对象

  • 定义

    通过类,可以定义变量。类定义出来的变量,也称为类的实例

  • 对象的内存分配

    和结构变量一样,对象所占用的内存空间的大小,等于所有成员变量的大小之和。
    每个对象各有自己的存储空间。一个对象的某个成员变量被改变了,不会影响到另一个对象。

  • 对象间的运算

    和结构变量一样,对象之间可以用 “=”进行赋值,但是不能用 “==”,“!=”,“>”,“<”“>=”“<=”进行比较,除非这些运算符经过了“重载”。

2.类

  • 定义:从客观事物抽象出类

    类是 C++ 的核心特性,通常被称为用户定义的类型。
    类用于指定对象的形式,它包含了数据表示法和用于处理数据的方法。

  • 示例:矩形类

    矩形的属性就是长和宽。因此需要两个变量,分别代表长和宽。
    矩形可以有设置长和宽,算面积,和算周长这三种行为。
    将长、宽变量和设置长,宽,求面积,以及求周长的三个函数“封装”在一起,就能形成一个“矩形类”。

 class CRectangle { public: int w, h; int Area() { return w * h; } int Perimeter(){ return 2 * ( w + h); } void Init( int w_,int h_ ) { w = w_; h = h_; } }; //必须有分号

二、成员变量&成员函数

1.使用类的成员变量和成员函数

  • 用法1:对象名.成员名
  CRectangle r1,r2; r1.w = 5; r2.Init(5,4);
  • 用法2. 指针->成员名
  CRectangle r1,r2; CRectangle * p1 = & r1; CRectangle * p2 = & r2; p1->w = 5; p2->Init(5,4); //Init作用在p2指向的对象上
  • 用法3:引用名.成员名
  CRectangle r2; CRectangle & rr = r2; rr.w = 5; rr.Init(5,4); //rr的值变了,r2的值也变

2.类成员的可访问范围

  • 访问修饰符

    类成员的访问限制是通过在类主体内部对各个区域标记 public、private、protected 来指定的。关键字 public、private、protected 称为访问修饰符。

    • 公有(public)成员

      公有成员在程序中类的外部是可访问的。可以不使用任何成员函数来设置和获取公有变量的值

    • 私有(private)成员(无关键字默认)

      私有成员变量或函数在类的外部是不可访问的,甚至是不可查看的。只有类和友元函数可以访问私有成员。
      默认情况下,类的所有成员都是私有的。

    • protected(受保护)成员

      受保护成员变量或函数与私有成员十分相似,但有一点不同,protected(受保护)成员在派生类(即子类)中是可访问的

  • 成员函数

    • 成员函数内部

      • 当前对象的全部属性、函数
      • 同类其它对象的全部属性、函数
    • 成员函数外部

      • 只能够访问该类对象的公有成员
  • 示例

class CEmployee
{private:char szName[30]; //名字
public:int salary; //工资void setName(char *name);void getName(char *name);void averageSalary(CEmployee e1, CEmployee e2);
};
void CEmployee::setName(char *name)
{strcpy(szName, name); //ok
}
void CEmployee::getName(char *name)
{strcpy(name, szName); //ok
}
void CEmployee::averageSalary(CEmployee e1,CEmployee e2)
{cout << e1.szName; //ok,访问同类其他对象私有成员salary = (e1.salary + e2.salary) / 2;
}
int main()
{CEmployee e;strcpy(e.szName, "Tom1234567889"); //编译错,不能访问私有成员e.setName("Tom"); // oke.salary = 5000;  //okreturn 0;
}
int main()
{CEmployee e;strcpy(e.szName, "Tom1234567889"); //编译错,不能访问私有成员e.setName("Tom"); // oke.salary = 5000;  //okreturn 0;
}
  • 隐藏

    设置私有成员的机制,叫“隐藏”
    “隐藏”的目的是强制对成员变量的访问一定要通过成员函数进行,那么以后成员变量的类型等属性修改后,只需要更改成员函数即可。否则,所有直接访问成员变量的语句都需要修改。

3.成员函数可以重载及参数缺省

  • 成员函数重载
#include <iostream>
using namespace std;
class Location
{private:int x, y;public:void init(int x = 0, int y = 0);void valueX(int val) { x = val; }int valueX() { return x; }
};
  • 成员函数缺省
class Location
{private:int x, y;public:void init(int x = 0, int y = 0);void valueX(int val = 0) { x = val; }int valueX() { return x; }
};
Location A;
A.valueX(); //错误,编译器无法判断调用哪个valueX

三、构造函数

1.构造函数概念

  • 成员函数的一种
  • 一个类可以有多个构造函数

2.构造函数定义

  • 名字与类名相同,可以有参数,不能有返回值(void也不行)

3.构造函数生成

  • 如果定义类时没写构造函数,则编译器生成一个默认的无参数的构造函数,默认构造函数无参数,不做任何操作
  • 如果定义了构造函数,则编译器不生成默认的无参数的构造函数
  • 对象生成时构造函数自动被调用。对象一旦生成,就再也不能在其上执行构造函数

4.构造函数作用

  • 作用是对对象进行初始化,如给成员变量赋初值
  • 构造函数执行必要的初始化工作,有了构造函数,就不必专门再写初始化函数,也不用担心忘记调用初始化函数。
  • 有时对象没被初始化就使用,会导致程序出错。

5.构造函数示例

  • 编译器自动生成
class Complex
{private:double real, imag;public:void Set(double r, double i);
};                         //编译器自动生成默认构造函数
Complex c1;                //默认构造函数被调用
Complex *pc = new Complex; //默认构造函数被调用
  • 可以有多个构造函数,参数个数或类型不同
class Complex
{private:double real, imag;public:void Set(double r, double i);Complex(double r, double i);Complex(double r);Complex(Complex c1, Complex c2);
};
Complex::Complex(double r, double i)
{real = r;imag = i;
}
Complex::Complex(double r)
{real = r;imag = 0;
}
Complex::Complex(Complex c1, Complex c2);
{real = c1.real + c2.real;imag = c1.imag + c2.imag;
}
Complex c1(3), c2(1, 0), c3(c1, c2);
// c1 = {3, 0}, c2 = {1, 0}, c3 = {4, 0};
  • 构造函数最好是public的,private构造函数不能直接用来初始化对象
class CSample
{private:CSample(){}
};
int main()
{CSample Obj; //err. 唯一构造函数是privatereturn 0;
}

四、复制构造函数

1.复制构造函数基本概念

  • 只有一个参数,即对同类对象的引用
  • 形如 X::X( X& )或X::X(const X &)
  • 如果没有定义复制构造函数,那么编译器生成默认复制构造函数。默认的复制构造函数完成复制功能
  • 如果定义的自己的复制构造函数,则默认的复制构造函数不存在。
  • 不允许有形如 X::X( X )的构造函数

2.复制构造函数起作用的三种情况

  • 1)当用一个对象去初始化同类的另一个对象时。
  Complex c2(c1); Complex c2 = c1; //初始化语句,非赋值语句
  • 2)如果某函数有一个参数是类 A 的对象,那么该函数被调用时,类A的复制构造函数将被调用。
class A
{public:A(){};A(A &a){cout << "Copy constructor called" << endl;}
};
void Func(A a1) {}
int main()
{A a2;Func(a2);return 0;
}
//程序输出结果为: Copy constructor called
    1. 如果函数的返回值是类A的对象时,则函数返回时,A的复制构造函数被调用:
class A
{public:int v;A(int n) { v = n; };A(const A &a){v = a.v;cout << "Copy constructor called" << endl;}
};
A Func()
{A b(4);return b;
}
int main()
{cout << Func().v << endl;return 0;
}
//输出结果:
//Copy constructor called
//4

3.注意:对象间赋值并不导致复制构造函数被调用

五、类型转换构造函数

1.类型转换构造函数基本概念

  • 定义转换构造函数的目的是实现类型的自动转换。
  • 只有一个参数,而且不是复制构造函数的构造函数,一般就可以看作是转换构造函数。
  • 当需要的时候,编译系统会自动调用转换构造函数,建立一个无名的临时对象(或临时变量)。

2.类型转换构造函数示例

class Complex
{public:double real, imag;Complex(int i){ //类型转换构造函数cout << "IntConstructor called" << endl;real = i;imag = 0;}Complex(double r, double i){real = r;imag = i;}
};
int main()
{Complex c1(7, 8);Complex c2 = 12;c1 = 9; // 9被自动转换成一个临时Complex对象cout << c1.real << "," << c1.imag << endl;return 0;
}

六、析构函数

1.析构函数基本概念

  • 名字与类名相同,在前面加‘~’, 没有参数和返回值,一个类最多只能有一个析构函数。
  • 析构函数对象消亡时即自动被调用。可以定义析构函数来在对象消亡前做善后工作,比如释放分配的空间等。
  • 如果定义类时没写析构函数,则编译器生成缺省析构函数。缺省析构函数什么也不做。
  • 如果定义了析构函数,则编译器不生成缺省析构函数。

2.析构函数示例

class String
{private:char *p;public:String(){p = new char[10];}~String();
};
String ::~String()
{delete[] p;
}

七、this指针

1.this指针的作用

  • 非静态成员函数中可以直接使用this来代表指向该函数 作用的对象的指针。
  class Complex{public:double real, imag;void Print() { cout << real << "," << imag; }Complex(double r, double i) : real(r), imag(i){}Complex AddOne(){this->real++;  //等价于 real ++;this->Print(); //等价于 Printreturn *this;}};

2.this指针和静态成员函数

  • 静态成员函数中不能使用 this 指针

    因为静态成员函数并不具体作用与某个对象

八、静态成员

1.静态成员基本概念

  • 在定义前面加了static关键字的成员
  class CRectangle{private:int w, h;static int nTotalArea; //静态成员变量static int nTotalNumber;public:CRectangle(int w_, int h_);~CRectangle();static void PrintTotal(); //静态成员函数}
  • 静态成员&普通成员

    • 普通成员变量每个对象有各自的一份,而静态成员变 量一共就一份,为所有对象共享。
  //sizeof 运算符不会计算静态成员变量。class CMyclass{int n;static int s;};//则 sizeof( CMyclass ) 等于 4
- 普通成员函数必须具体作用于某个对象,而静态成员函数并不具体作用于某个对象。

2.静态成员的访问

静态成员不需要通过对象就能访问

    1. 类名::成员名
  CRectangle::PrintTotal();
    1. 对象名.成员名
  CRectangle r; r.PrintTotal();
    1. 指针->成员名
  CRectangle * p = &r; p->PrintTotal();
    1. 引用.成员名
  CRectangle & ref = r; int n = ref.nTotalNumber;

3.静态成员注意事项

  • 在静态成员函数中,不能访问非静态成员变量,也不能调用非静态成员函数。

九、成员对象和封闭类

1.封闭类定义

有成员对象的类叫 封闭(enclosing)类

class CTyre //轮胎类
{private:int radius; //半径int width;  //宽度
public:CTyre(int r, int w) : radius(r), width(w) {}
};
class CEngine //引擎类
{};
class CCar
{ //汽车类
private:int price; //价格CTyre tyre;CEngine engine;public:CCar(int p, int tr, int tw);
};
CCar::CCar(int p, int tr, int w) : price(p), tyre(tr, w){};
int main()
{CCar car(20000, 17, 225);return 0;
}

2.封闭类构造函数和析构函数的执行顺序

  • 封闭类对象生成时,先执行所有对象成员的构造函数,然后才执行封闭类的构造函数。
  • 对象成员的构造函数调用次序和对象成员在类中的说明次序一致,与它们在成员初始化列表中出现的次序无关。
  • 当封闭类的对象消亡时,先执行封闭类的析构函数,然后再执行成员对象的析构函数。次序和构造函数的调用次序相反。

3.封闭类实例

class CTyre
{public:CTyre() { cout << "CTyre contructor" << endl; }~CTyre() { cout << "CTyre destructor" << endl; }
};
class CEngine
{public:CEngine() { cout << "CEngine contructor" << endl; }~CEngine() { cout << "CEngine destructor" << endl; }
};
class CCar
{private:CEngine engine;CTyre tyre;public:CCar() { cout << “CCar contructor” << endl; }~CCar() { cout << "CCar destructor" << endl; }
};

4.封闭类的复制构造函数

封闭类的对象,如果是用默认复制构造函数初始化的,那么它里面包含的成员对象, 也会用复制构造函数初始化。

十、友元

1.友元函数

  • 一个类的友元函数可以访问该类的私有成员
  class CCar; //提前声明 CCar类,以便后面的CDriver类使用class CDriver{public:void ModifyCar(CCar *pCar); //改装汽车};class CCar{private:int price;friend int MostExpensiveCar(CCar cars[], int total); //声明友元friend void CDriver::ModifyCar(CCar *pCar);          //声明友元};友元(friends, P199) void CDriver::ModifyCar(CCar *pCar){pCar->price += 1000; //汽车改装后价值增加}int MostExpensiveCar(CCar cars[], int total)//求最贵汽车的价格{int tmpMax = -1;for (int i = 0; i < total; ++i)if (cars[i].price > tmpMax)tmpMax = cars[i].price;return tmpMax;}int main(){return 0;}

2.友元类

  • 如果A是B的友元类,那么A的成员函数可以访问B的私有成员
  class CCar{private:int price;friend class CDriver; //声明CDriver为友元类};class CDriver{public:CCar myCar;void ModifyCar(){                        //改装汽车myCar.price += 1000; //因CDriver是CCar的友元类,//故此处可以访问其私有成员}};int main() { return 0; }

3.友元类注意事项

友元类之间的关系不能传递,不能继承

十一、常量成员函数

如果一个成员函数中没有调用非常量成员函数 ,也没有修改成员变量的值,那么,最好将其 写成常量成员函数。

1.常量成员函数基本概念

  • 在定义常量成员函数和声明常量成员函数时都应该使用const 关键字
class Sample
{private:int value;public:void PrintValue() const;
};
void Sample::PrintValue() const
{ //此处不使用const会//导致编译出错cout << value;
}
void Print(const Sample &o)
{o.PrintValue(); //若 PrintValue非const则编译错
}
  • 常量成员函数内部不能改变属性的值,也不能调用非常量成员函数
class Sample
{private:int value;public:void func(){};Sample() {}void SetValue() const{value = 0; // wrongfunc();    //wrong}
};
const Sample Obj;
Obj.SetValue(); //常量对象上可以使用常量成员函数

2.常量成员函数的重载

  • 两个函数,名字和参数表都一样,但是一个是const,一个不是,算重载。
  int main(){const CTest objTest1;CTest objTest2;cout << objTest1.GetValue() << "," << objTest2.GetValue();return 0;}//= > 1, 2

3.mutable成员变量

  • 可以在const成员函数中修改的成员变量
  class CTest{public:bool GetData() const{m_n1++;return m_b2;}private:mutable int m_n1;bool m_b2;};

【知识索引】【C++入门】

【C++入门】C++类和对象相关推荐

  1. python入门笔记——类和对象⑤(继承)

    python入门笔记--类和对象⑤(继承) # python中展现面向对象的三大特征:封装.继承.多态 # 封装:把内容封装到某个地方以便后续的使用 # 对封装来说,其实就是使用初始化构造方法将内容封 ...

  2. 学习笔记:C++初阶【C++入门、类和对象、C/C++内存管理、模板初阶、STL简介、string、vector、list、stack、queueu、模板进阶、C++的IO流】

    文章目录 前言 一.C++入门 1. C++关键字 2.命名空间 2.1 C语言缺点之一,没办法很好地解决命名冲突问题 2.2 C++提出了一个新语法--命名空间 2.2.1 命名空间概念 2.2.2 ...

  3. C++入门学习 类与对象

    类与对象 普通大一新生,C++入门.老师上课不讲课只看视频讲解,效率低.临近期末总结巩固已经学习过的内容. 一.构造函数 定义 类对象被创建时,编译系统对象分配内存空间,并自动调用该构造函数-> ...

  4. java构造方法 隐含三步_Java入门总结--------类和对象关系以及构造方法

    Java中重写父类的方法要遵循"两同两小一大"规则, "两同"即方法名相同.形参列表相同: "两小"指的是子类方法的返回值类型应比父类方法返 ...

  5. Python入门--创建类的对象

    class Student:native_pace = '山东' # 直接写在类里的变量称为类属性# 初始化方法def __init__(self, name, age):self.na = name ...

  6. c++入门(类和对象and继承)

    文件名:<1> time.h :<2> time.cpp :<3> DateTime.h :<4> DateTime.cpp :<5> ma ...

  7. 【C++入门】类和对象(中)

    文章目录 一.类的默认成员函数 1. 构造函数 2. 析构函数 3. 拷贝构造函数 4. 赋值运算符重载 5. const成员 6. 取地址及const取地址操作符重载 一.类的默认成员函数 如果一个 ...

  8. python入门——P40类和对象:一些相关的BIF

    一些相关的BUF issubclass(class, classinfo) class是classinfo的子类则返回true 1.一个类会被认为是自身的子类 2.classinfo可以是类对象组成的 ...

  9. python入门——P39类和对象:拾遗

    组合 组合就是把旧类实例化放到新类里面进行调用,代码如下 class Chairs():def __init__(self,x):self.num = xclass Glasses():def __i ...

  10. python入门——P37类和对象:面向对象编程

    self是什么 class相当于房子图纸,每个对象是参照图纸建立的实际的房子,self相当于每一栋房子的门牌号,在下面这段代码里,每个对象都是调用了自己那栋房子里的方法,就是因为self tips:在 ...

最新文章

  1. css设定div固定比例,响应式网页中,如何只用CSS实现div的高和宽保持固定比例
  2. Redis的常用命令——set的常用命令
  3. TF之DNN:对DNN神经网络进行Tensorboard可视化(得到events.out.tfevents本地服务器输出到网页可视化)
  4. xargs的简单解析
  5. cxf 本地wsdl_cxf使用wsdl文件生成代码
  6. linux我ll查不到usr,Linux学习-文件查寻
  7. textarea 输入框限制字数
  8. [bzoj 2017] [Usaco2009 Nov]硬币游戏
  9. 基于ASP的校园二手交易网设计与实现程序免费下载
  10. JS判断字符串包含的方法
  11. java中no enclosing instance of type * is accessible的解决方法
  12. 调用虚拟内存编译时的error处理
  13. 杜拉拉升职记摘录:早日实现退休理想--你需要眼光和资格
  14. 蓝队应对攻击的常用策略三
  15. Python开发语音聊天机器人
  16. 编好的C语言程序怎么放记事本上运行,怎么用记事本运行程序
  17. 在线 LaTeX 公式编辑器
  18. php接入aws短信,亚马逊短信(AWS-SMS)
  19. freeradius mysql ad_freeradiusmysql简单配置一例
  20. exagear安装java_exagear模拟器怎么使用 exagear模拟器使用方法安装教程

热门文章

  1. Open browser failed!! Please check if you have installed the browser correct
  2. 量子计算机代表人物,量子力学究竟“可怕”在哪?科学家的怀疑或许是对的
  3. vue和哪个php框架搭配,vue配什么ui框架比较好
  4. python替换img的路径为新的路径_python – Django |连接路径位于基本路径组件之外{%static img.thumbnail.url%},错误400与whitenoise...
  5. 的有效性最好_股票职业玩家教韭菜实战,验证技术指标的有效性,资产增值是王道...
  6. 二叉树类图_数据结构(十四)——二叉树
  7. 信息系统安全等级保护基本要求_继电保护对电力系统安全运行至关重要,电网对它的基本要求有哪些...
  8. java单链表选票_Hackerrank Practice
  9. android 内存检测开源库 翻译,开源 | 哈佛大学NLP组开源神经机器翻译工具包OpenNMT:已达到生产可用水平...
  10. python列表方法图解_python中list(列表)的使用方法总结(图文)