十、C++中的类 class与struct的区别

2023-05-16

面向对象程序设计,需要诸如类和对象这样的概念。

C++支持面向过程、基于对象、面向对象、泛型编程四种

C语言不支持面向对象编程

类是一种将数据和函数组织在一起的方式。

一个函数参数过多,代码不好维护,可创建一个类,一次性包含所有想要的数据,最终作为一个类型。

类必须是唯一的类型名,因为类基本上就是我们创建一个新的变量类型,类使用{}括起来,但是结尾还有一个“;”符号。

由类 类型制成的变量叫做对象,新创建对象的过程叫做实例化。

【结构体struct和类class区别在于权限,class默认private,struct默认public】

访问控制:当创建一个类是,可以指定类中属性的可见性,默认情况下,类中的成员的访问控制都是私有的,只有类内部的函数才能访问这些变量。如果想要在main函数中访问这些变量,类需要被定义为共有的,共有表示被允许在类外访问这些变量。

类的创建与访问:

#include <iostream>
#define LOG(x) std::cout << x << std::endl

class Player
{
public:
	int x, y;
	int speed = 2;
};
int main()
{
	Player player;//使用类,前面是类名,后面随意,类型为Player的player变量
	player.x = 5;
	std::cin.get();
}

类的移动,编写函数改变X,Y变量,

#include <iostream>
#define LOG(x) std::cout << x << std::endl

class Player
{
public:
	int x, y;
	int speed = 2;
};

void move(Player& player, int xa, int ya)//接收要移动的Player,引用传递
{
	player.x += xa * player.speed;
	player.y += ya * player.speed;
}

int main()
{
	Player player;
	move(player, 1, -1);
	std::cin.get();
}

类中可以包含函数,可以移动move函数到类内,类内的函数被称作method(方法),函数在类内,访问函数变量时就不需要再传player对象。

#include <iostream>
#define LOG(x) std::cout << x << std::endl

class Player
{
public:
	int x, y;
	int speed = 2;

	void move( int xa, int ya)//接收要移动的Player,引用传递
	{
		x += xa * speed;
		y += ya * speed;
	}
};

int main()
{
	Player player;
	player.move(1, -1);
	std::cin.get();
}

类就是能使我们对变量进行组织,变成一个类型。这些变量还可以添加函数。

18

在C++中结构体struct与类class的区别:

让一个类的成员在默认情况下是私有的,编译时会得到错误。报错类里的某一个变量是无法访问的,因为按照预设值,这个变量是私有,只有类中的方法(method,其实是类中定义的函数)才能访问类中的变量。所以要添加public。

默认情况下,类是私有的(如果没有指定任何类型的可见修饰符,或者没有指定任何内容)。

而struct默认是共有的。如果要将结构体变为私有,要明确写出private。作用上没有太大区别,但是在代码实际使用时确实有所不同。结构体存在的原因,保持与C之间的兼容性,C中没有类,只有结构体。

谈论plain old data(pod)时,尽可能使用struct,只是在谈论某种结构,仅仅代表变量,如向量。

//想定义一个结构,将两个浮点数放在一起,比如Vec2
struct Vec2//Vec2结构只是浮点数的表现形式
{
	float x, y;//仅仅将两个变量按字面意思组合起来

	void Add(const Vec2& other)//添加方法,接收另一个Vec2
	{
		x += other.x;
		y += other.y;
	}
};

结构体最好不要使用继承。如果要用一个完整的类层次或某种继承层次,建议使用类。因为继承又增加了另一层复杂性,结构体建议仅仅是数据结构体。

建议struct仅仅存储数据,涉及到别的建议使用类。

19

如何创建一个类

创建Log类

Log是我们管理Log信息的一种方式,是把我们想要的信息打印到控制台上,这在调试程序时很有用。在我们的程序应用中如果你想知道发生了什么,只需要把事物的状态打印到控制台上就可以。控制台就像是信息转储的地方,可以用来显示发生了什么,这是几乎可以保证程序正确运行的方式,在游戏应用中我们要显示一个图像或者其他东西,这有时候会出现问题,然而控制台是内置在操作系统中的程序,所以它几乎总是正常工作的,。Log类可以根据需求写的很简单,也同样可以很复杂,但是它对开发和调试很重要。

日志系统不止可以把信息打印到控制台,也可以打印不同的颜色,或者把日志输出到文件、网络等。

最简单的log类,仅仅实现向控制台发送文本,可以控制发送给控制台log信息量的级别,最开始有三个级别,错误error、警告warning和信息message(或者叫跟踪trace)三个。

        把日志级别设置为warning时,只有warning和error级别的log信息可以打印出来,message(trace)级别的不行。当只需要查看程序的警告与报错信息时可以这样设置。

①创建一个log类

相像log类是如何工作的,创建一个类或者设计一个API的方式是研究它的使用情况。

class Log

{

};

②进入main函数,开始编写我们如何使用log类

实例化一个类、需要指定一个log级别作为它的实参。先跳过这一步;//设置一个log级别,因此要有一个SetLevel方法,参数为LogLevelWarning指warning级别。只有warning和error级别的log信息可以打印出来,message(trace)级别的不行。//打印一个warning信息,log.Warn("Hello!")...

以上知道了log类需要那些功能,现在去定义中实现。

③编写log类

public,显示SetLevel函数。用一个整数代表log级别。warn函数有一个字符串指针,是我们要打印的消息,const char* 是字符串的意思。声明LogLevelWarning存在,声明log level变量。创建私有变量成员代表设置的log级别,整数型的变量名称m_LogLevel,m前缀表示是私有类的成员变量.

设置2为message(trace)级别,1代表warning,0代表error。创建变量,他们的值代表我们要表示的东西。把LogLevelWarning设置为共有变量。

public方法放在一部分,public变量放在另一部分,public static变量在另一部分。设置的值都是常数,所以要写const int 然后设置LogLevelWarning的值,

#include <iostream>
#define LOG(x) std::cout << x << std::endl

class Log
{
public:
	const int LogLevelError = 0;
	const int LogLevelWarning = 1;
	const int LogLevelInfo = 2;
private:
	int m_LogLevel = LogLevelInfo;//默认情况下所有东西都需要打印
public:
	void SetLevel(int level)
	{
		if (m_LogLevel >= LogLevelError)
			m_LogLevel = level;//函数中变量的引用
	}

	void Error(const char* message)
	{
		if (m_LogLevel >= LogLevelError)
			std::cout << "[ERROR]:" << message << std::endl;
	}

	void Info(const char* message)
	{
		if (m_LogLevel >= LogLevelInfo)
			std::cout << "[INFO]:" << message << std::endl;
	}

	void Warn(const char* message)
	{
		if (m_LogLevel >= LogLevelWarning)
			std::cout << "[WARNING]:" << message << std::endl;
	}
};



int main()
{
	Log log;//首先进行实例化
	log.SetLevel(log.LogLevelWarning);//设置警告等级,警告或错误才会被打印
	log.Warn("Hello");//设置Log警告信息“Hello”
	log.Error("Hello"); 
	log.Info("Hello");
	std::cin.get();
}

 由于log级别被设置为warning,所以info消息没有被打印。

如果不设置log级别,默认会设为info

#include <iostream>
#define LOG(x) std::cout << x << std::endl

class Log
{
public:
	const int LogLevelError = 0;
	const int LogLevelWarning = 1;
	const int LogLevelInfo = 2;
private:
	int m_LogLevel = LogLevelInfo;//默认情况下所有东西都需要打印
public:
	void SetLevel(int level)
	{
		if (m_LogLevel >= LogLevelError)
			m_LogLevel = level;//函数中变量的引用
	}

	void Error(const char* message)
	{
		if (m_LogLevel >= LogLevelError)
			std::cout << "[ERROR]:" << message << std::endl;
	}

	void Info(const char* message)
	{
		if (m_LogLevel >= LogLevelInfo)
			std::cout << "[INFO]:" << message << std::endl;
	}

	void Warn(const char* message)
	{
		if (m_LogLevel >= LogLevelWarning)
			std::cout << "[WARNING]:" << message << std::endl;
	}
};



int main()
{
	Log log;//首先进行实例化
	//log.SetLevel(log.LogLevelWarning);//设置警告等级,警告或错误才会被打印
	log.Warn("Hello");//设置Log警告信息“Hello”
	log.Error("Hello"); 
	log.Info("Hello");
	std::cin.get();
}

 运行代码,三种消息都会被打印出来。

20

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

十、C++中的类 class与struct的区别 的相关文章

  • PHP - 扩展 __construct

    我想知道你是否可以帮助我 我有两个类 一个扩展了另一个 B 类将由各种不同的对象扩展 并用于常见的数据库交互 现在我希望 B 类能够处理其连接和断开连接 而无需来自 A 类或任何外部输入的指示 据我了解 问题是扩展类不会自动运行其 cons
  • 无法在类对象的 ArrayList 中存储值。 (代码已编辑)

    这基本上是一个 Java 代码转换器 它涉及一个 GUI 让用户输入类类型 名称和方法 为了存储值 我创建了一个类VirtualClass与ArrayList
  • 将 null 转换为对象?

    我今天遇到了这段代码 AsyncInvoke OnTimeMessageTimer object null ElapsedEventArgs null 有没有什么问题 有时 当方法重载时 您需要这样做 以告诉编译器您正在调用哪一个 null
  • 构造函数中显式关键字的使用

    我试图了解 C 中显式关键字的用法 并查看了这个问题C 中的explicit关键字是什么意思 https stackoverflow com questions 121162 但是 那里列出的示例 实际上是前两个答案 对于用法并不是很清楚
  • 匿名结构体作为返回类型

    下面的代码编译得很好VC 19 00 23506 http rextester com GMUP11493 标志 Wall WX Za 与VC 19 10 25109 0 标志 Wall WX Za permissive 这可以在以下位置检
  • 错误:无效使用不完整类型“类 Move”/未定义对 Move::NONE 的引用

    拜托 我不知道为什么这个简单的代码被拒绝 它给了我 2 个编译错误 请帮帮我 I use 代码 块 20 03 我的编译器是GNU GCC 移动 hpp class Move public Move Move int int public
  • 如何调用超类方法,就像在派生类中定义的那样?

    我有这些课程 class Control get code return 3 getCodeChain var result this code if super getCodeChain result result concat supe
  • 来自另一个类的 Qt C++ GUI 调用

    我通过 gui 拖放创建了一个按钮和一个文本浏览器 UI 以及单击按钮功能是在 mainwindow cpp 中创建的 有一个 main cpp 但这是无关紧要的 因为在单击开始按钮之前程序不会启动 include mainwindow h
  • 模板继承内部类访问问题

    我不敢相信gcc不会接受以下代码 请告诉我是否确实不可能从基本模板访问内部类 或者我是否遗漏了某些内容 template
  • 如何在函数内 malloc 结构体数组?代码以其他方式工作

    我正在尝试创建一个函数来创建可变大小的二维函数数组 我正在使用以下代码 它本身似乎工作得很好 typedef struct Starter Properties int TypeB int TypeF int TypeW Randomize
  • 如何在 Julia 中引用结构本身

    我有这个代码 struct MyStruct text String function MyStruct text String text text do other things end end 当我写这篇文章时 我意识到朱莉娅没有认识到
  • 为什么方法引用不跟踪这一点?

    我正在使用 Babel 来转译 ES2015 类 class Foo constructor foo this foo foo sayFoo console log this foo 如果我说这样的话 这个课程的效果就完全符合我的预期foo
  • PHP Microsoft Excel 文件生成/导出类

    我一直在寻找一个好的 Excel 文件生成类 但还没有找到 我的首要问题是 虽然我可以在 Excel 中打开导出的文件 运行 2007 年 但我总是收到一条警告 文件的格式与文件扩展名不同 我注意到 phpMyAdmin 中的 Excel
  • jqGrid如何将额外的类应用于标题列

    我想在特定列上应用一个额外的类 我知道通过在 colModel 中指定这一点对于行是可能的 但这些类仅应用于 结果行 中的列 而不应用于标题 我想要达到的是通过简单的类名隐藏较小视口的特定列 与 Twitter Bootstrap 一起使用
  • 公共领域有哪些替代方案?

    我正在用 java 编写一个游戏 正如问题标题建议的那样 我在类中使用公共字段 暂且 据我所知 公共领域很糟糕 我有一些理解其中的原因 但如果有人能澄清为什么你不应该使用它们 那将不胜感激 问题是 从我所看到的来看 这似乎是合乎逻辑的 是使
  • 具有成员 std::mutex (或其他不可复制对象)的类的复制或移动构造函数?

    class A private class B private std mutex mu A parent NULL public B A const parent ptr parent parent ptr B const A B b c
  • 寻找一种简单的方法来重新初始化结构

    我有一个名为 CoolStruct 的结构 struct CoolStruct int id uint32 type uint32 subtype String name 我也有这些结构的向量 std vector
  • C++ 实现友元/内联函数

    我似乎找不到这个新手问题的答案 如果我有课 头文件 h Class X public friend bool operator const X const X inline size type rows const ETC 当我去实现X的
  • Exit() 时是否调用基本对象析构函数?

    我意识到这个问题已经出现过几次 但我试图获得上述问题的明确答案 但我不断遇到相互矛盾的信息 我需要知道的是 当我使用 exit 时 基本类对象是否被破坏 我知道需要删除动态内存 但我的意思更像是 include
  • VBA全局类变量

    我的障碍是试图让多个子程序识别类变量 当我尝试全局声明它们时 出现编译错误 无效的外部过程 然后 当我运行公共函数或子函数来声明变量时 它们在其他子函数中保持未定义状态 我希望多个子程序能够识别变量 因为它们的值应该通过用户窗体进行更改 然

随机推荐