struct and class

struct

struct 和 class 都是由各种数据组成的集合(也叫做类),这些数据可以是整数,浮点数,字符,也可以是函数。在代码中,我们首先定义集合的名字,包含的数据类别。之后可以命名需用的集合,在主函数或者一些函数中对这些集合调用。

先对 struct 做一个示例:

#include<iostream>
using namespace std;
//定义一种结构体的名字,之后你可以把node理解为和int,string同样效果的东西 
struct node{
	int x,y;//定义node中我要包含的数据 
};
int main()
{
	node a;//定义一个变量a,他的数据类型就是你的node
	//然后你就可以对a里面的数据调用
	a.x=1;a.y=2;
	cout<<a.x<<endl;
	cout<<a.y<<endl; 
	return 0;
}

struct 里面也可以进行函数的定义。并可以直接调用自身所包含的数据并作出修改。(调用自身的含义,是指不需要使用 \(a.x\) 而可以直接写 \(x\))。

#include<iostream>
using namespace std;
struct node{
	int x,y;
	void add(){
		x=x+y;
	}
};
int main()
{
	node a;
	a.x=1;a.y=2;
	cout<<a.x<<endl;
	cout<<a.y<<endl; 
	a.add();
	cout<<a.x<<endl;
	return 0;
}

数据权限

class 和 struct 最大的区别,在于数据权限的默认值,数据权限分为三种:public, private, protected。

public: main 函数和子类 class 可以调用。
private: main 函数和子类 class 都不可以调用。
protected: main 函数不可以,子类 class 可以调用。

我们用代码及结果来理解权限的含义

class A{
	public:
		int x;
	protected:
		int y;
	private:
		int z;
}
int main()
{
	A a;
	cout<<a.x;//1
	cout<<a.y;//2
	cout<<a.z;//3
}

这样写只有语句1可以正常输出,语句2,3都会使你编译错误。

子类的写法:

class B: <type> A

这样的写法表示 B 继承了 A 里面所有权限为 public 和 protected的数据.

继承后的权限则由你所写的 type 决定,我们考虑三种权限限制程度递进为:public,protected,private。type是你希望改变的权限,各数据会在原本的权限和 type 间进行比较,选择限制程度更深的那个。具体可以将type分为两类:

public: A 中 public 和 protected 权限不变的继承给 B。
private/protected: A 中 public 和 protected 继承给 B 后权限均更改为 type。

class A
{
	protected:
		int x;
};

class B : public A{
	public:
		void print(){
			cout<<x;
		}
};
int main()
{
	B b;
	b.print();
}

这里就是 \(x\) 在 A 中为 protected,你用 public 去继承,它的权限保持不变,你就必须用函数去输出他,而不是直接 \(cout<<b.x\)

总结下需要注意的两点是:

1.子类不可调用基类的 private。
2.子类调用数据后,权限是二者比较,取限制更深。

这里就可以提到 struct 和 class 的区别:如果不定义数据权限,struct 里面的值默认为 public,而 class 里面的值默认为 private。这就是为什么我们不用在 struct 里面定义数据权限,他就可以在主函数里面被调用,直接做各种计算。

所以对于 class,我们一般会定义权限为 public 的函数,来对 private 的数据进行读入,计算,输出。如:

class A{
	public:
		void print(){
			cout<<x;
		}
	private:
		int x=2;
};
int main()
{
	A a;
	a.print();
}

构造函数(Constructors)

对类的数据成员进行初始化,对各个数据赋予初始值。

为什么要有这个函数?对于普通的局部变量来说,如果不赋予初值,那么他的初始值是随机的,所以初始化就非常重要,例如一个人的年龄不可能是负数,在不初始化的情况下,可能出现一些预估外的错误。

构造函数的形式为:

class A{
	public:
		A(int a){
			x=a;
		}
		void print(){
			cout<<x;
		}
	private:
		int x;
};
int main()
{
	A a(2);
	a.print();
}

一个 class 可以写多个构造函数,区分它们的方法是 \(A()\) 括号中的内容,我们去定义class变量时,如上述代码中的 \(a(2)\),系统会根据括号里的数据类型去匹配你写的构造函数,然后执行。

代码示例

class info{
	public:
		info(){//对应下面的a
			name="unknown";
			age=0;
		}
		info(string s){//对应下面的b
			name=s;
			age=0;
		}
		info(int a){//对应下面的c
			name="unknown";
			age=a;
		}
		info(string s,int a){//对应下面的d
			name=s;
			age=a;
		}
		void getname(string s){
			name=s;
		}
		void printname(){
			cout<<name<<endl;
		}
		void getage(int b){
			age=b;
		}
		void printage(){
			cout<<age<<endl;
		}
	private:
		string name;
		int age;
};
int main()
{
	info a,b("Niu"),c(18),d("Zhao",20);
	a.printname();
	a.printage();
	b.printname();
	b.printage();
	c.printname();
	c.printage();
	d.printname();
	d.printage();
	return 0;
}

输出结果

析构函数(Destructor)

在类的定义时,名称与类名相同,增加一个~,一般用于释放对象所占用的资源,在对象消失时调用。
析构函数也可以有多个。
如果没有手动写析构函数,编译器会生成一个默认析构函数,并调用。

class  Student
{
    public:
        Student()  //构造函数
        {
            cout << "调用构造函数"<< endl;
        }
        ~Student()
        {
            cout << "调用析构函数" << endl;
        }
};

int main()
{
	Student A;
	cout<<1;
}

在不存在额外操作的情况下,class会在创造他的代码结束后被清除,比如这里输出的最终结果就应该是“构造,1,析构”。

posted on 2023-10-19 15:39  漠寒·  阅读(193)  评论(0编辑  收藏  举报