首页 > 编程语言 >C++——类

C++——类

时间:2024-05-20 23:29:29浏览次数:27  
标签:函数 静态 double 成员 C++ void 构造函数

C++学习

一、定义

class 类名
{
    public:  //外界可以直接访问或者调用
 
    private: //不能被外部所访问或调用, 只能被本类内部访问
};

二、类的成员函数

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

  • 成员函数可以定义在类定义内部,或者单独使用范围解析运算符 :: 来定义。

class Box
{
   public:
      double length;      // 长度
      double breadth;     // 宽度
      double height;      // 高度
   
      double getVolume(void)
      {
         return length * breadth * height;
      }
};

或是:

double Box::getVolume(void)
{
    return length * breadth * height;
}

三、访问修饰符

class Base {
 
   public:
  // 公有成员
 
   protected:
  // 受保护成员
 
   private:
  // 私有成员
 
};

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

- protected 受保护成员
protected(受保护)成员在派生类(即子类)中是可访问的。
在这里 width 成员可被派生类 smallBox 的任何成员函数访问。

#include <iostream>
using namespace std;
 
class Box
{
   protected:
      double width;
};
 
class SmallBox:Box // SmallBox 是派生类
{
   public:
      void setSmallWidth( double wid );
      double getSmallWidth( void );
};
 
// 子类的成员函数
double SmallBox::getSmallWidth(void)
{
    return width ;
}
 
void SmallBox::setSmallWidth( double wid )
{
    width = wid;
}
 
// 程序的主函数
int main( )
{
   SmallBox box;
 
   // 使用成员函数设置宽度
   box.setSmallWidth(5.0);
   cout << "Width of box : "<< box.getSmallWidth() << endl;
 
   return 0;
}

- private 私有成员
私有成员变量或函数在类的外部是不可访问的,甚至是不可查看的。只有类和友元函数可以访问私有成员。
默认情况下,类的所有成员都是私有的。
实际操作中,我们一般会在私有区域定义数据,在公有区域定义相关的函数,以便在类的外部也可以调用这些函数,如下所示:

#include <iostream>
 
using namespace std;
 
class Box
{
   public:
      double length;
      void setWidth( double wid );
      double getWidth( void );
 
   private:
      double width;
};
 
// 成员函数定义
double Box::getWidth(void)
{
    return width ;
}
 
void Box::setWidth( double wid )
{
    width = wid;
}
 
// 程序的主函数
int main( )
{
   Box box;
 
   // 不使用成员函数设置长度
   box.length = 10.0; // OK: 因为 length 是公有的
   cout << "Length of box : " << box.length <<endl;
 
   // 不使用成员函数设置宽度
   // box.width = 10.0; // Error: 因为 width 是私有的
   box.setWidth(10.0);  // 使用成员函数设置宽度
   cout << "Width of box : " << box.getWidth() <<endl;
 
   return 0;
}

输出
Length of box : 10
Width of box : 10

继承中的修饰符:
有public, protected, private三种继承方式,它们相应地改变了基类成员的访问属性。

1.public 继承:基类 public 成员,protected 成员,private 成员的访问属性在派生类中分别变成:public, protected, private

2.protected 继承:基类 public 成员,protected 成员,private 成员的访问属性在派生类中分别变成:protected, protected, private

3.private 继承:基类 public 成员,protected 成员,private 成员的访问属性在派生类中分别变成:private, private, private

但无论哪种继承方式,上面两点都没有改变:

1.private 成员只能被本类成员(类内)和友元访问,不能被派生类访问;

2.protected 成员可以被派生类访问。
在这里插入图片描述

四、类的构造函数 ~
类的构造函数是类的一种特殊的成员函数,它会在每次创建类的新对象时执行
构造函数的名称与类的名称是完全相同的,并且不会返回任何类型,也不会返回 void。构造函数可用于为某些成员变量设置初始值。

#include <iostream>
 
using namespace std;
 
class Line
{
   public:
      void setLength( double len );
      double getLength( void );
      Line();  // 这是构造函数
 
   private:
      double length;
};
 
// 成员函数定义,包括构造函数
Line::Line(void)
{
    cout << "Object is being created" << endl;
}
 
void Line::setLength( double len )
{
    length = len;
}
 
double Line::getLength( void )
{
    return length;
}
// 程序的主函数
int main( )
{
   Line line;
 
   // 设置长度
   line.setLength(6.0); 
   cout << "Length of line : " << line.getLength() <<endl;
 
   return 0;
}

Object is being created
Length of line : 6

默认的构造函数没有任何参数,但如果需要,构造函数也可以带有参数。这样在创建对象时就会给对象赋初始值。

构造函数可分为:无参构造函数、有参构造函数、拷贝构造函数(参数为const ClassName &vriable 这个比较复杂)。

默认是无参数构造函数, 当你想在构造的时候传参数进去, 那么自己就要写个有参数的构造函数;
例如:
class A1{ //使用默认构造函数,无参数
}
class A2{
A2(int c){ m_c=c } //有参数构造函数, 可以传达一个值初始化成员变量
int m_c;
}
调用:
A1 a1; //默认构造函数, 无参数
A2 a2(10); //有参数构造函数, 传达参数10,初始化成员变量 a2.m_c;

C++默认提供拷贝构造函数是指向的浅拷贝。只是进行了简单的成员变量的值的复制。

五、类的析构函数

  • 类的析构函数是类的一种特殊的成员函数,它会在每次删除所创建的对象时执行。
  • 析构函数的名称与类的名称是完全相同的,只是在前面加了个波浪号(~)作为前缀,它不会返回任何值,也不能带有任何参数。析构函数有助于在跳出程序(比如关闭文件、释放内存等)前释放资源
#include <iostream>
 
using namespace std;
 
class Line
{
   public:
      void setLength( double len );
      double getLength( void );
      Line();   // 这是构造函数声明
      ~Line();  // 这是析构函数声明
 
   private:
      double length;
};
 
// 成员函数定义,包括构造函数
Line::Line(void)
{
    cout << "Object is being created" << endl;
}
Line::~Line(void)
{
    cout << "Object is being deleted" << endl;
}
 
void Line::setLength( double len )
{
    length = len;
}
 
double Line::getLength( void )
{
    return length;
}
// 程序的主函数
int main( )
{
   Line line;
 
   // 设置长度
   line.setLength(6.0); 
   cout << "Length of line : " << line.getLength() <<endl;
 
   return 0;
}

Object is being created
Length of line : 6
Object is being deleted

六、拷贝构造函数
拷贝构造函数是一种特殊的构造函数,它在创建对象时,是使用同一类中之前创建的对象来初始化新创建的对象。拷贝构造函数通常用于:

  1. 通过使用另一个同类型的对象来初始化新创建的对象。

  2. 复制对象把它作为参数传递给函数。

  3. 复制对象,并从函数返回这个对象。

  4. 如果在类中没有定义拷贝构造函数,编译器会自行定义一个。如果类带有指针变量,并有动态内存分配,则它必须有一个拷贝构造函数。拷贝构造函数的最常见形式如下:

classname (const classname &obj) {
   // 构造函数的主体
}

七、友元函数
类的友元函数是定义在类外部,但有权访问类的所有私有(private)成员和保护(protected)成员。尽管友元函数的原型有在类的定义中出现过,但是友元函数并不是成员函数
友元可以是一个函数,该函数被称为友元函数;友元也可以是一个类,该类被称为友元类,在这种情况下,整个类及其所有成员都是友元。
如果要声明函数为一个类的友元,需要在类定义中该函数原型前使用关键字 friend,如下所示:

#include <iostream>
 
using namespace std;
 
class Box
{
   double width;
public:
   friend void printWidth( Box box );    //友元函数
   void setWidth( double wid );
};
 
// 成员函数定义
void Box::setWidth( double wid )
{
    width = wid;
}
 
// 请注意:printWidth() 不是任何类的成员函数
void printWidth( Box box )
{
   /* 因为 printWidth() 是 Box 的友元,它可以直接访问该类的任何成员 */
   cout << "Width of box : " << box.width <<endl;
}
 
// 程序的主函数
int main( )
{
   Box box;
 
   // 使用成员函数设置宽度
   box.setWidth(10.0);
   
   // 使用友元函数输出宽度
   printWidth( box );
 
   return 0;
}

八、内联函数
C++ 内联函数是通常与类一起使用。如果一个函数是内联的,那么在编译时,编译器会把该函数的代码副本放置在每个调用该函数的地方。
如果想把一个函数定义为内联函数,则需要在函数名前面放置关键字 inline,在调用函数之前需要对函数进行定义。如果已定义的函数多于一行,编译器会忽略 inline 限定符。
在类定义中的定义的函数都是内联函数,即使没有使用 inline 说明符。

九、this 指针
在 C++ 中,每一个对象都能通过 this 指针来访问自己的地址。this 指针是所有成员函数的隐含参数。因此,在成员函数内部,它可以用来指向调用对象

  • 友元函数没有 this 指针,因为友元不是类的成员。只有成员函数才有 this 指针。
  • this指针在成员函数的开始执行前构造的,在成员的执行结束后清除。
  • this指针不能再静态函数中使用
#include <iostream>
 
using namespace std;
 
class Box
{
   public:
      // 构造函数定义
      Box(double l=2.0, double b=2.0, double h=2.0)
      {
         cout <<"Constructor called." << endl;
         length = l;
         breadth = b;
         height = h;
      }
      double Volume()
      {
         return length * breadth * height;
      }
      int compare(Box box)
      {
         return this->Volume() > box.Volume();   //this指针
      }
   private:
      double length;     // Length of a box
      double breadth;    // Breadth of a box
      double height;     // Height of a box
};
 
int main(void)
{
   Box Box1(3.3, 1.2, 1.5);    // Declare box1
   Box Box2(8.5, 6.0, 2.0);    // Declare box2
 
   if(Box1.compare(Box2))
   {
      cout << "Box2 is smaller than Box1" <<endl;
   }
   else
   {
      cout << "Box2 is equal to or larger than Box1" <<endl;
   }
   return 0;
}

C++指针
C语言指针

十、指向类的指针

一个指向类的指针与指向结构的指针类似,访问指向类的的指针的成员,需要使用成员访问运算符—>,就像访问指向结构的指针一样,与所有的指针一样,在使用前必须对指针初始化

十一、静态变量和静态方法

== 想 ==
1、静态对象

1)使用static关键字把类成员声明为静态时,后续无论创建多少个类对象,静态成员都只有一个副本;

2)静态成员在类的所有对象中都是共享的,如果不存在其他初始化语句,在创建第一个对象时,所有的静态数据都会被初始化为零
我们不能把静态成员的初始化放置在类的定义中,但是可以在类的外部使用范围解析运算符::来重新声明静态变量从而对它进行初始化;

3)静态成员变量在类中仅仅是声明,没有定义,所以要在类的外面定义,实际上是给静态成员变量分配内存,如果不加定义就会报错,初始化是一个赋初始值,而定义是分配内存。

2、静态方法

1)如果把函数成员声明为静态的,就可以把函数与类的任何特定对象独立开来。静态成员函数即使在类对象不存在的情况下也能被调用,静态函数 只能使用类名 范围解析运算符:: 就可以访问。

2)静态成员函数只能访问静态成员数据,其他静态成员函数和类外部的其他函数。

3)静态成员函数只有一个类范围,他不能访问this指针,可以使用静态成员函数来判断类的某些对象是否已被创建。

4)静态成员函数与普通成员函数的区别:静态成员函数没有this指针,只能访问静态成员(包括静态成员变量和静态成员函数);普通成员函数有this指针,可以访问类中的任意成员,而静态成员函数没有this指针。

#include <iostream>
#include <string>
 
class Pet
{
public:
	Pet(std::string theName);
	~Pet();
 
	static int  getCount();   //静态方法只有Pet类,外部对象调用时的接口
 
protected:
	std::string name;
private:                       //只有类里边的方法才能访问
	static int count;     //静态属性只有Pet类
};
 
class Dog : public Pet   //Dog来继承Pet的类
{
public :
	Dog(std::string theName);
};
 
class Cat : public Pet   //Cat来继承Pet的类
{
public:
	Cat(std::string theName);
};
 
int Pet::count = 0;   //定义分配内存,初始化赋初始值  1.编译器为count分配内存;2.把count这个变量初始化为0;
 
Pet::Pet(std::string theName) //Pet的构造函数
{
   	name = theName ;
	count++;
	std::cout<<"一只宠物出生了,它的名字叫:"<<name<<"\n";
};
 
Pet::~Pet() // Pet的析构函数
{
	count--;
	std::cout<<name<<"挂掉了\n";
}
 
int Pet::getCount()//getCount这个接口函数的作用就把count输出来
{
	return count;
}
 
Dog::Dog(std::string theName) : Pet(theName)
{
}
 
Cat::Cat(std::string theName) : Pet(theName)
{
}
 
int main()
{
	Dog dog("Tom");
	Cat cat("Jerry");
 
	std::cout<<"\n已经诞生了"<<Pet::getCount()<<"只宠物!\n\n";  //访问方法
 
	{                       //大括号的作用
		Dog dog_2("Tom_2");
		Cat cat_2("Jerry_2");
 
		std::cout<<"\n现在呢,已经诞生了"<<Pet::getCount()<<"只宠物!\n\n";
	}
	std::cout<<"\n现在还剩下"<<Pet::getCount()<<"只宠物!\n\n";
 
	
	getchar();
	return 0;
}

运行结果如下图所示:

静态成员在类的所有对象中是共享的。如果不存在其他的初始化语句,在创建第一个对象时,所有的静态数据都会被初始化为零。我们不能把静态成员的初始化放置在类的定义中,但是可以在类的外部通过使用范围解析运算符 :: 来重新声明静态变量从而对它进行初始化,如下面的实例所示。

#include <iostream>
 
using namespace std;
 
class Box
{
   public:
      static int objectCount;
      // 构造函数定义
      Box(double l=2.0, double b=2.0, double h=2.0)
      {
         cout <<"Constructor called." << endl;
         length = l;
         breadth = b;
         height = h;
         // 每次创建对象时增加 1
         objectCount++;
      }
      double Volume()
      {
         return length * breadth * height;
      }
   private:
      double length;     // 长度
      double breadth;    // 宽度
      double height;     // 高度
};
 
// 初始化类 Box 的静态成员
int Box::objectCount = 0;
 
int main(void)
{
   Box Box1(3.3, 1.2, 1.5);    // 声明 box1
   Box Box2(8.5, 6.0, 2.0);    // 声明 box2
 
   // 输出对象的总数
   cout << "Total objects: " << Box::objectCount << endl;
 
   return 0;
}

Constructor called.
Constructor called.
Total objects: 2

静态成员函数:
如果把函数成员声明为静态的,就可以把函数与类的任何特定对象独立开来。静态成员函数即使在类对象不存在的情况下也能被调用,静态函数只要使用类名加范围解析运算符 :: 就可以访问。

静态成员函数只能访问静态成员数据、其他静态成员函数和类外部的其他函数。

静态成员函数有一个类范围,他们不能访问类的 this 指针。您可以使用静态成员函数来判断类的某些对象是否已被创建。

标签:函数,静态,double,成员,C++,void,构造函数
From: https://www.cnblogs.com/hedy77/p/18203060

相关文章

  • c++菱形继承、多态与类内存模型
    目录1.菱形继承1.1.菱形继承的问题1.2.解决办法2.虚函数与多态2.1.普通函数不能实现多态2.2.虚函数(子类重写)+父类指向子类——实现多态2.3.多态原理3.c++内存模型4.参考1.菱形继承先看下面的例子,SheepTuo同时继承了Sheep和Tuo,而他们同时继承Animal类#include<iostream>usin......
  • C++基础知识学习笔记(1)
    资料来源https://www.bilibili.com/video/BV1et411b73Z/?spm_id_from=333.337.search-card.all.click&vd_source=cc561849591f6a210152150b2493f6f3简单知识点创建项目用VS创建了一个C++的空项目。在【源文件】中创建一个cpp文件书写以下代码并运行#include<iostr......
  • C++常用模板
    常用模板:1.组合数(注意\(N\)与\(mod\))点击查看代码#include<bits/stdc++.h>usingnamespacestd;#definelllonglongconstllN=1e3+10,mod=998244353;lln,a[N],jc[N],dp[N],ans;voidinit(){ jc[0]=1; for(inti=1;i<N;i++)jc[i]=jc[i-1]*i%mod;}llksm......
  • C++的四种智能指针及简单实现
    C++的四种智能指针及简单实现参考:C++智能指针讲解及模拟实现一、auto_ptrauto_ptr有拷贝语义,拷贝后源对象变为空指针,可能引发严重问题template<classT>classmy_unique_ptr{private:T*_ptr;public://普通构造函数my_unique_ptr(T*ptr):_ptr(ptr){}......
  • C++算法刷题基础
    1.main函数的返回类型一定是int2.C++语言为我们准备了一组内置库,包含了很多常用的功能,并且这些内置库可以直接使用,而其中的内置库:iostream,就提供了输入和输出的功能,允许开发者从键盘读取输入并在屏幕上输出结果。3.在iostream库中,我们有两个对象可以使用,分别是cin和cout。......
  • 侯捷C++上期笔记
    1.头文件和类、构造函数c++和c最大的不同在于C++会把数据以及处理数据的函数放到一个对象objects(class)里,不同类之间不可见,类似C中结构体struct防止头文件重复声明ifndefcomplex//当之前没有声明过这个头文件时,才进行后续的声明definecomplex(2)补充定义(1)类定义(3)类功能解释......
  • C++身份证二要素实名认证api、实名认证接口
    在数字化时代背景下,个人信息安全成为了社会关注的焦点。为进一步加强网络空间的安全管理,提升服务效率,身份证实名认证接口的出现为各行业提供了更为安全、高效的身份验证解决方案。随着互联网+政务服务、金融科技、电子商务等领域的快速发展,实名认证需求日益增长。翔云身......
  • C++ 异常处理注意事项总结
    C++异常处理注意事项总结:异常安全代码:编写异常安全的代码是至关重要的。这意味着你的代码应该在面对异常时能够正确地清理资源并维持程序状态。使用RAII(ResourceAcquisitionIsInitialization)技术可以帮助自动管理资源,减少内存泄漏的风险。使用noexcept:对于不会抛出异常......
  • C++ 多线程编程要点总结
    C++多线程编程要点总结:选择合适的线程库:C++11引入了 <thread> 头文件,提供了对线程的原生支持。也可以使用第三方库,如Boost.Thread,它提供了更多高级功能和更好的跨平台兼容性。线程创建与管理:使用 std::thread 类创建新线程,并传入函数或可调用对象作为线程的入口......
  • C++中 符号的优先级
    符号运算顺序::从左至右a++a--type()type{}a()a[].->从左至右!~++a--a+a-a(type)sizeof&a*anewnew[]deletedelete[]从右至左.*->*从左至右a*ba/ba%b从左至右a+ba-b从左至右<<>>从左至右<<=>>=从左至右==!......