类和对象 面向对象的编程

文章详细介绍了C++中的类和对象的概念,包括数据抽象、类的成员函数(如构造函数和析构函数)、静态成员、头文件的包含问题、this指针以及友元函数和友元类的使用。通过示例代码展示了如何定义和使用这些概念,强调了数据隐藏和封装在提高代码可维护性和可复用性方面的重要性。
摘要由CSDN通过智能技术生成

类和对象

1.数据抽象

  • 忽略一个主题中与当前问题无关的方面,以便更充分地注意与当前问题有关的方面
  • 只向外界提供关键信息,并隐藏其后台的实现细节,即只表现必要的信息而不呈现细节
  • 好处:
    • 类的内部受到保护,不会因无意的用户级错误导致对象状态受损。
    • 数据抽象有助于提高代码的可维护性和可复用性。它将数据的表示和操作进行了封装,使得用户只需关注接口的使用,而无需关心底层的实现。这样可以降低代码的耦合度,提高代码的灵活性和可扩展性。
// 抽象数据类型 - 矩形
class Rectangle {
private:
  int length;
  int width;
  
public:
  void setLength(int len) {
    length = len;
  }
  
  void setWidth(int wid) {
    width = wid;
  }
  
  int getArea() {
    return length * width;
  }
};

Rectangle类表示一个矩形,它包含了矩形的长度和宽度。通过设置访问器函数(setLength和setWidth)和获取器函数(getArea),外部用户可以通过这些接口来操作矩形对象,而无需了解矩形对象内部是如何实现的。


2.类

定义:描述数据抽象的结果,实现对数据和函数的封装

类的成员函数

把定义和原型写在类定义内部的函数,就像类定义中的其他变量一样。类成员函数是类的一个成员,它可以操作类的任意对象,可以访问对象中的所有成员。

  • 成员函数可以定义在类定义内部。在类定义中定义的成员函数把函数声明为内联的,即便没有使用 inline 标识符。
class Box
{
   public:
      double length;      // 长度
      double breadth;     // 宽度
      double height;      // 高度
   
      double getVolume(void)
      {
         return length * breadth * height;
      }
};


  • 或者单独使用范围解析运算符 :: 来定义
  • 在这里,需要强调一点,在 :: 运算符之前必须使用类名。调用成员函数是在对象上使用点运算符(.
double Box::getVolume(void)
{
    return length * breadth * height;
}
#include <iostream>
 
using namespace std;
 
class Box
{
   public:
      double length;   // 长度
      double breadth;  // 宽度
      double height;   // 高度
      // 成员函数声明
      double get(void);
      void set( double len, double bre, double hei );
};
// 成员函数定义
double Box::get(void)
{
    return length * breadth * height;
}
 
void Box::set( double len, double bre, double hei)
{
    length = len;
    breadth = bre;
    height = hei;
}
int main( )
{
   Box Box1;        // 声明 Box1,类型为 Box
   Box Box2;        // 声明 Box2,类型为 Box
   Box Box3;        // 声明 Box3,类型为 Box
   double volume = 0.0;     // 用于存储体积
 
   // box 1 详述
   Box1.height = 5.0; 
   Box1.length = 6.0; 
   Box1.breadth = 7.0;
 
   // box 2 详述
   Box2.height = 10.0;
   Box2.length = 12.0;
   Box2.breadth = 13.0;
 
   // box 1 的体积
   volume = Box1.height * Box1.length * Box1.breadth;
   cout << "Box1 的体积:" << volume <<endl;
 
   // box 2 的体积
   volume = Box2.height * Box2.length * Box2.breadth;
   cout << "Box2 的体积:" << volume <<endl;
 
 
   // box 3 详述
   Box3.set(16.0, 8.0, 12.0); 
   volume = Box3.get(); 
   cout << "Box3 的体积:" << volume <<endl;
   return 0;
}
//需要注意的是,私有的成员和受保护的成员不能使用直接成员访问运算符 (.) 来直接访问

3.构造函数与析构函数

class CMyString
{
	public:
		//构造函数
		CMyString(char* s) 
		{
			str = new char[strlen(s) + 1];
			strcpy(str, s);
		}
		//析构函数 
		~CMyString() 
		{
			delete[] str;
		}
	private:
		char* str;
};

构造函数(Constructor)

是一种特殊的成员函数,用于创建对象时进行初始化操作。它具有与类同名的特殊函数,没有返回类型(包括void),在对象创建时自动被调用。创建类的对象时,自动调用类的构造函数 。 创建一个对象时只调用一个构造函数(根据参数列表)且只在创建时调用一次。构造函数可以进行一些对象的默认初始化,分配内存空间,执行必要的设置等操作。它可以有多个重载形式,根据参数列表的不同,选择不同的构造函数来创建对象。

class MyClass {
public:
  // 默认构造函数
  MyClass() {
    // 初始化操作
  }
  
  // 带参数的构造函数
  MyClass(int value) {
    // 初始化操作
  }
};
重载构造函数

类的构造函数可以重载,重载的构造函数的函数名完全相同,都没有返回值类型,但参数列表各不相同,类有多个构造函数时,系统根据创建对象时提供的参数来确定调用哪个构造函数,创建一个对象时只会根据参数列表调用类的一个构造函数, 而且只调用一次,不会调用所有构造函数

默认构造函数

不需要任何参数的构造函数是默认构造函数,一个类不能同时拥有多个默认构造函数

复制构造函数
  • 在创建对象时,是使用同一类中之前创建的对象来初始化新创建的对象
  • 复制构造函数的参数是该类的对象,一般使用传引用的方式
#include<iostream>
using namespace std;
class Complex{
public:
    double real, imag;
    Complex(double r,double i){
        real = r; imag = i;
    }
    Complex(const Complex & c){
        real = c.real; imag = c.imag;
        cout<<"Copy Constructor called"<<endl ;
    }
};

int main(){
    Complex cl(1, 2);
    Complex c2 (cl);  //调用复制构造函数
    cout<<c2.real<<","<<c2.imag;
    return 0;
}
#include<iostream >
using namespace std;
class Complex
{
public:
    double real, imag;
    Complex(double r, double i) {
        real= r; imag = i;
    }
};
int main(){
    Complex cl(1, 2);
    Complex c2 (cl);  //用复制构造函数初始化c2
    cout<<c2.real<<","<<c2.imag;  //输出 1,2
    return 0;
}
析构函数(Destructor)

是另一个特殊的成员函数,用于在对象销毁时进行清理工作。它具有与类同名的特殊函数,以波浪号(~)开头,没有参数和返回值,也不能带有任何参数。析构函数在对象被销毁时自动被调用,用于释放对象占用的资源,执行必要的收尾操作。

class MyClass {
public:
  // 构造函数
  MyClass() {
    // 初始化操作
  }
  
  // 析构函数
  ~MyClass() {
    // 清理操作
  }
};

4.类的静态成员

  • 关键字:static

  • 声明方式:static + 数据函数定义

  • 静态成员在类的所有对象中是共享的。如果不存在其他的初始化语句,在创建第一个对象时,所有的静态数据都会被初始化为零。

  • 静态成员函数只能访问类的静态成员,不能调用非静态成员函数和访问非静态数据成员

  • 静态成员函数与普通成员函数的区别:

    • 静态成员函数没有 this 指针,只能访问静态成员(包括静态成员变量和静态成员函数)。

    • 普通成员函数有 this 指针,可以访问类中的任意成员;而静态成员函数没有 this 指针。

  • 访问静态成员的方式:

    • 对象名 + 点操作符 (.)
    • 对象的引用 + 点操作符 (.)
    • 类指针 + 箭头操作符 (->)
    • 类名 + 作用域运算符(::)

5.头文件的包含问题

  • 头文件会被其他头文件或源文件包含
  • 一个源文件可能会多次包含一个头文件
  • C++允许嵌套包含,但不允许递归包含
  • #pragma once让头文件只被编译一次,作用对象是物理文件,由编译器防止被包含内容的重复定义

6.this指针

  • 每个对象都有一个指向自身的this指针
  • 对象调用成员函数时会将自己的this指针传递给成员函数 (隐含参数)
  • this是一个隐藏的指针,可以在类的成员函数中使用,它可以用来指向调用对象
  • 成员函数访问对象的所有数据成员都是通过this指针(基地址)访问
  • 友元函数没有 this 指针,因为友元不是类的成员,只有成员函数才有 this 指针
class Test {
public:
	Test(int n = 0) {
		data = n;
	}
	void print() {
		cout << "data = " << this->data << "!" << endl;
	}
private:
	int data;
};

  • 类的静态成员函数为什么不能访问非静态数据成员?

    • 静态成员函数(属于类)没有维护this指针
    • 访问非静态数据成员(属于对象)需要this指针
  • 静态成员函数为什么不能调用非静态成员函数

    • 调用非静态成员函数需要一个隐含参数(this指针)
    • 静态成员函数没有

7.友元函数和友元类

类的数据成员都设为私有的——良好的程序设计风格
如果某个(些)外部函数需要访问类的数据成员,怎么办?

  • 方法一:数据公有
  • 方法二:友元
友元函数
  • 友元函数是外部函数

  • 友元函数具有访问类的所有成员的权限 ,有权访问类的所有私有(private)成员和保护(protected)成员

  • 声明友元函数的方法: friend + 函数原型

  • 除非能带来极大的便利,否则不要使用友元

    class Triangle
    {
    	//声明setA是本类的友元函数
    friend void setA(Triangle& t, int n);
    public:
    	Triangle(int x = 5, int y = 5, int z = 5);
    	void print();
    private:
    	int a, b, c;
    };
    
友元类

一个类的友元类的所有成员函数都有访问类的所有成员的权限

友元类的声明方法: friend + class +类名

class B;
class A 
{
public:
	void setB(B& b, int m);
	void print(B& b);
};
class B 
{
	friend class A; //声明友元类
private:
	int data;
};

void setA(Triangle& t, int n);
public:
Triangle(int x = 5, int y = 5, int z = 5);
void print();
private:
int a, b, c;
};


#### 友元类

一个类的友元类的所有成员函数都有访问类的所有成员的权限

友元类的声明方法: ==friend + class +类名==

```cpp
class B;
class A 
{
public:
  void setB(B& b, int m);
  void print(B& b);
};
class B 
{
  friend class A; //声明友元类
private:
  int data;
};

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值