公有继承(Public Inheritance)

news/2025/1/9 10:43:12/文章来源:https://www.cnblogs.com/xixi100/p/18661386

初学者浅析C++类与对象
C++类与对象
class
class基本语法
class ClassName {
public:
// 公有成员
Type memberVariable; // 数据成员
ReturnType memberFunction(); // 成员函数声明

private:
// 私有成员
Type privateMemberVariable; // 数据成员
ReturnType privateMemberFunction(); // 成员函数声明

protected:
// 保护成员
Type protectedMemberVariable; // 数据成员
ReturnType protectedMemberFunction(); // 成员函数声明
};
Important points

public :公有访问权限,类的外部可以访问

private:私有访问权限,只有类的内部可以访问。

protected:保护访问权限,只有类的内部和派生类可以访问。

注意,默认权限为private

这里可以实现成员变量的被操作权限

在class中,声明数组大小时,如果声明大小使用的变量为class内的变量时,应当如下

class Map{
public:
const static int maxn =4343;
int next[maxn]={};
};
或者建议使用 array 或者 vector

关于class中的static修饰词警示后人

在class中访问没有static修饰的函数与变量都是需要一个已经创建的对象才可以访问。

但是有了static修饰以后便会有所不同。有static修饰的变量和函数仅仅属于这个类本身,不属于某个特定的对象,但是其仍然拥有访问权限的设置!!

其可以直接被如下方式访问

class classname{
public:
static functionname(){/content/}
static cnt;
};

int main (){
classname::functionname();
cout<<classname::cnt<<endl;
}
构造函数与析构函数
构造函数语法:类名(){}

构造函数,没有返回值也不写void
函数名称与类名相同
构造函数可以有参数,因此可以发生重载
程序在调用对象时候会自动调用构造,无须手动调用,而且只会调用一次
析构函数语法: ~类名(){}

析构函数,没有返回值也不写void
函数名称与类名相同,在名称前加上符号 ~
析构函数不可以有参数,因此不可以发生重载
程序在对象销毁前会自动调用析构,无须手动调用,而且只会调用一次
注: 这两个函数会被设置访问权限,可以限制类的创建和销毁!!

构造函数分类与调用
两种分类方式:

​ 按参数分为: 有参构造和无参构造

​ 按类型分为: 普通构造和拷贝构造

三种调用方式:

​ 括号法 ``````

​ 显示法

​ 隐式转换法

深拷贝与浅拷贝的差别:

浅拷贝(Shallow Copy)
浅拷贝是指复制对象时,新的对象和原始对象共享相同的内存地址。换句话说,浅拷贝仅复制对象的值(即指针和基本数据类型的值),而不是指针所指向的实际对象。

特点:

共享引用: 如果对象包含指针或引用,浅拷贝只复制指针的值,因此原始对象和拷贝对象的指针会指向同一块内存区域。
性能: 浅拷贝比深拷贝通常更快,因为它只需要复制指针和基本数据类型的值,而不需要递归地复制所有引用的对象。
潜在问题: 由于原始对象和拷贝对象共享相同的内存区域,当一个对象修改了指针指向的内容时,另一个对象的内容也会受到影响。此共享可能导致悬挂指针(如果一个对象释放了共享内存,另一个对象会变成悬挂状态)或数据不一致的问题。
深拷贝(Deep Copy)
深拷贝则是创建一个新对象,并递归地复制原始对象所引用的所有对象。换句话说,深拷贝不仅复制对象的值,还复制对象内包含的所有指针指向的对象,从而创建一个完全独立的新对象。

特点:

独立性: 原始对象和深拷贝对象之间没有共享的内存区域,修改一个对象不会影响另一个对象。
性能: 深拷贝可能较慢,因为它涉及递归地复制所有指针所指向的内容。
内存管理: 深拷贝通常需要编写额外的代码来确保正确管理内存,例如在析构函数中释放分配的内存,避免内存泄漏。
构造函数的初始化列表
class Person {
public:

////传统方式初始化
//Person(int a, int b, int c) {
//	m_A = a;
//	m_B = b;
//	m_C = c;
//}//初始化列表方式初始化
Person(int a, int b, int c) :m_A(a), m_B(b), m_C(c) {}
void PrintPerson() {cout << "mA:" << m_A << endl;cout << "mB:" << m_B << endl;cout << "mC:" << m_C << endl;
}

private:
int m_A;
int m_B;
int m_C;
};
类对象作为类成员的构造和析构函数调用顺序
C++类中的成员可以是另一个类的对象,我们称该成员为 对象成员

//构造的顺序是 :先调用对象成员的构造,再调用本类构造
//析构顺序与构造相反
静态成员
静态成员变量
所有对象共享同一份数据

在编译阶段分配内存

类内声明,类外初始化(一定要记着初始化,不然编译错误不显示!!!)

class Example {
public:
static int staticVar; // 声明静态成员变量
};

int Example::staticVar = 0; // 定义并初始化静态成员变量
静态成员函数(static)
所有对象共享同一个函数
静态成员函数只能访问静态成员变量(其实只需要在参数上加入一个对象就可以访问对象的成员变量)
静态函数可以在类里面声明,在类外定义!!

常成员(const)
const 修饰成员函数
保证不会改变对象的状态,但是可以调用更改 static 修饰的变量

只可以调用其他const成员函数

为了保证在const成员函数中,不会对对象进行改变

可以调用静态函数!!!

可以返回一个值,但是如果返回的是指针or引用,则必须加上const

class Type{
int a;
const int* GO() const{//int const* GO() const 这样也可以
return &a;
}
};
这一条并不适用于 static变量: 当返回的值为static变量的地址或引用时,可以不用static

注意:在这里在再次区分一下 const int * int const * int * const

前两者是一样的,定义的指针不可以修改对应的地址

第三者是指该指针所指的地址不可修改,但是可以通过指针修改内容

成员变量加上
m
u
t
a
b
l
e
就可以不受以上规则限制,而可被const函数修改和返回非常量指针

总结: 常函数保证了不会通过其对对象有任何形式的修改包括指针与引用,但是对应于
s
t
a
t
i
c
,
m
u
t
a
b
l
修饰的变量例外

const关键字的使用方式:

const int* () const{}
前一个
c
o
n
s
t
用于修饰返回值,后一个用于修饰函数为静态函数

注意:函数可以反回
c
o
n
s
t
的值,但是没有意义,因为其返回的值是拷贝。但是返回
c
o
n
s
t
的指针与引用是有意义的。

const MyClass& getObject() const {
static MyClass obj;
return obj;
}
OR
const MyClass* getObject() const {
static MyClass obj;
return obj;
}
常对象
声明对象前加const称该对象为常对象
常对象只能调用常函数
常对象可以修改静态变量,调用静态函数,修改
m
u
t
a
b
l
e
变量
友元
通过声明友元的方式,可以使C++中某个类的private和protected的变量和函数被其他类和函数访问

友元类
友元类函数
友元全局函数
class People{
friend class Dorm; //友元类
friend void get_password(const People&,const Dorm&); //友元函数
public:
const int ID;
void Change_drompassword(const int&,const int&,const int &,Dorm&);
public:
People(int id,int Password): ID(id),password(Password){
cout<<"creat a new person\n";
}
private:
int password;
};

class Dorm{
friend class People;
friend void get_password(const People & a,const Dorm & b);
friend void People::Change_drompassword(const int&,const int&,const int &,Dorm&); //友元类函数
private:
int get_number(){
return dorm_number;
}
int dorm_number;
int dorm_password;
public:
Dorm(int number,int password):dorm_number(number),dorm_password(password){
cout<<"creat a drom!\n";
}
};
Attention:

在声明友元类函数之前,一定要保证该类已经被声明完成(提前声明不可以,因为complier只是知道了有这个类而不知道这个类的具体内容)。例如:将以上代码的两个类的定义交换位置为导致
i
n
c
o
m
p
l
e
t
i
n
g
错误
在声明有友元函数时,参数列表不用写参数名称,但是
c
o
n
s
t

,
&

不可拉下
友元的注意事项
不具有继承关系:友元关系不会被继承。例如,如果类B是类A的友元,类C继承了类A,类C不会自动成为类B的友元。
友元不具有传递性:如果类A是类B的友元,类B不是自动成为类A的友元。
友元关系是单向的:即使类A是类B的友元,类B并不能自动访问类A的私有成员,除非类B也显式地声明类A为友元。
C
+
+
中的输入输出流
输入流
用于从外部源(如键盘或文件)读取数据。

主要的输入流对象是std::cin,它表示标准输入流。

cin.fail() 用于检查输入是否成功

cin.ignore() 函数

忽略指定数量的字符

std::cin.ignore(count);//count 代表数量
忽略直到特定字符或 EOF:

std::cin.ignore(count, delimiter);//delimiter 代表分隔符,这个分隔符也会被舍去
std::cin.ignore(numeric_limitsstd::streamsize::max(), '\n')://忽略输入流中的特定字符或直到遇到换行符。
输出流
用于将数据输出到外部目标(如显示器或文件)。
主要的输出流对象是std::cout,它表示标准输出流。
cout.flush() 刷新输出流,确保所有缓冲区的数据被输出到终端。
错误流
用于输出错误信息。

主要的错误流对象是std::cerr,它用于打印错误信息。

日志流(Log Stream)
用于输出警告或日志信息。
主要的日志流对象是std::clog。
注: 以上四个标准流的使用方法都是一样的

int x;
std::cin >> x;
std::cout << "Hello, World!" << std::endl;
std::cerr << "An error occurred!" << std::endl;
std::clog << "This is a log message." << std::endl;
文件流
除了标准流,C++还支持文件流,用于从文件中读取数据或将数据写入文件。文件流的主要类有:

std::ifstream:用于输入文件流。
std::ofstream:用于输出文件流。
std::fstream:用于读写文件流(即同时支持输入和输出)。

include

include // 引入文件流

int main() {
// 写入文件
std::ofstream outFile("example.txt");
if (outFile.is_open()) {
outFile << "Hello, File!" << std::endl;
outFile.close();
}

// 读取文件
std::ifstream inFile("example.txt");
std::string line;
if (inFile.is_open()) {while (getline(inFile, line)) {std::cout << line << std::endl;}inFile.close();
}return 0;

}

文件打开模式
首先在打开文件流是可以设置打开模式的,设置方法如下

std::fstream file("example.txt", std::ios::in | std::ios::out | std::ios::ate);
注: 当要使用多个打开模式时,可以用 | 将其链接

接下来介绍文件打开模式

std::ios::in:用于读操作。

std::ios::out:用于写操作,文件内容会被覆盖(如果文件存在)。

std::ios::app:用于追加操作,所有写入的数据会追加到文件末尾。

std::ios::ate:文件打开时将文件指针定位到文件末尾,适用于需要在文件末尾开始读写的情况。

std::ios::trunc:如果文件已经存在,会清空文件内容,通常与 std::ios::out 一起使用。

std::ios::binary 以二进制的方式打开文件,不会进行仍何文本转化(比如换行符转化)

include

include

include

int main() {
// 文件名
const char* filename = "example.bin";

// 打开文件以二进制模式
std::ifstream file(filename, std::ios::binary);// 检查文件是否成功打开
if (!file) {std::cerr << "无法打开文件: " << filename << std::endl;return 1;
}// 移动文件指针到文件末尾以获取文件大小
file.seekg(0, std::ios::end);
std::streamsize size = file.tellg();
file.seekg(0, std::ios::beg);// 使用 std::vector 存储文件内容
std::vector<char> buffer(size);// 读取文件内容到 buffer 中
if (file.read(buffer.data(), size)) {// 处理文件内容(示例中仅输出文件大小)std::cout << "文件大小: " << size << " 字节" << std::endl;// 这里可以根据需要处理 buffer 中的数据
} else {std::cerr << "读取文件失败" << std::endl;
}// 关闭文件
file.close(mwgw.cn/?id=46328);return 0;

}
/*
文件名:你需要指定你想要读取的文件名。示例中使用的是 "example.bin"。

打开文件:std::ifstream file(filename, std::ios::binary); 这行代码打开了指定的文件,并以二进制模式进行读取。

获取文件大小:使用 seekg 和 tellg 方法来确定文件的大小。

读取内容:file.read(buffer.data(mwgw.cn/?id=44913), size); 这行代码将文件内容读取到 buffer 中。

错误检查:在打开文件和读取文件后,检查是否成功执行这些操作。

关闭文件:使用 file.close(mwgw.cn/?id=45198&qZ7q=sX); 关闭文件。
*/
以上打开方式在 ifstream ofstream 中使用是没有问题的,只不过要注意不要把输出的文件打开方式安在输入文件流上面了,会导致文件流无法正常打开的问题

最后让我们来介绍一下在 fstream 中使用这些文件打开方式会出现的一些问题

单独使用 app,ate,trunc 都是不行的,因为他们没有给出文件的读写模式,所以要加上 in out

有个作死的玩法

fstream IN(".in", std::ios::out);
cout<<IN.is_open(mwgw.cn/?id=43972)<<endl;
int a;
IN>>a;
IN<<1111<<endl;
然后你就会发现输出了个寂寞

定位输出指针
std::ios::beg /mwgw.cn/?id=47386&vJ8c=yZ/开头指针
std::ios::cur /mwgw.cn/?id=45373&kF6i=oT/当前指针
std::ios::end /mwgw.cn/?id=45665&wG1j=oJ/文件末尾
搭配函数 seekg() 使用

// 将读指针移动到文件开头

inFile.seekg(0, std::ios::beg);
// 将读指针移动到当前指针位置向后偏移5个字符的位置
inFile.seekg(5, std::ios::cur);
i
s
t
r
e
a
m

o
s
t
r
e
a
m
这两是流的两种类型,是最基础的,一个是输入流,一个是输出流

重载运算符的时候就是用的这两

//笔者摆烂了,BF5见!

运算符重载
重载函数的两种形式
重载函数和其他函数一样都会存在访问权限问题!!!

友函数重载
class Grade{
friend ostream& operator<<(ostream& out,const Grade & P);
private:mwgw.cn/?id=46018&kX2m=kG
int grade_Chnese,grade_program,grade_math;
Grade(int a,int b,int c,bool OP):grade_Chnese(a),grade_program(b),grade_math(c){
if(OP) cout<<"insert grade succesfully!\n";mwgw.cn/?id=44901
}
Grade(mwgw.cn/?id=47171&bB9j=kU){mwgw.cn/?id=45014}
};

ostream& operator <<(ostream & OUTT,const Cnt & b){mwgw.cn/?id=45326
OUTT<<b.cnt<<endl;
return OUTT;
}
注: 在友函数重载中,两个参数分别代表左右操作符(其实也可以不用加 friend 如果不用访问 private 和 protected 的话)

成员函数重载
class Grade{
public:
Grade operator + (const Grade& A) const{mwgw.cn/?id=46703
return Grade(A.grade_Chnese+grade_Chnese,A.grade_program+grade_program,A.grade_math+grade_math,0);
}
}
注: 在成员函数重载中对象本身会作为左操作数,参数作为右操作数

运算符重载实例
注: + - * / > < >= <= == 都比较简单,参考结构体重构一样的

注: 建议在定义参数时使用常变量+引用,防止意外的更改以及加快速度

左移右移符号(输入输出流操作符)
由于在左移右移符号中,对象始终处于右操作数,所以只可以使用友函数的方法

class Grade{
friend ostream& operator<<(ostream& out,const Grade & P);
friend class People;
private:mwgw.cn/?id=47369
int grade_Chnese,grade_program,grade_math;
Grade(int a,int b,int c,bool OP):grade_Chnese(a),grade_program(b),grade_math(c){
if(OP) cout<<"insert grade succesfully!\n";mwgw.cn/?id=43702&jK2y=sB
}
Grade(mwgw.cn/?id=44199){}
public:mwgw.cn/?id=44674
Grade operator + (const Grade& A) const{
return Grade(A.grade_Chnese+this->grade_Chnese,A.grade_program+this->grade_program,A.grade_math+this->grade_math,0);
}
};

ostream& operator<<(ostream& Gut,const Grade & P){mwgw.cn/?id=43660&uB5x=fV
Gut<<P.grade_Chnese<<" "<<P.grade_program<<" "<<P.grade_math<<endl;mwgw.cn/?id=46523&zH6y=nA
return Gut;mwgw.cn/?id=43725&aQ9x=yJ
}
自增自减符号
class Cnt{mwgw.cn/?id=45156&j5q=zT
public:
double cnt;mwgw.cn/?id=45078
Cnt(long double a=0){cnt=a;}
Cnt& operator ++(){
(this->cnt)+=1;
return this;mwgw.cn/?id=45794
}//先修改,后返回引用
Cnt operator ++(int){//这个int用于占位,是C++编译器用于区分这两个重载的标志,无实际意义!!
Cnt a=
this;mwgw.cn/?id=43725&aQ9x=yJ
cnt+=1;mwgw.cn/?id=45430&iT6y=xI
return a;mwgw.cn/?id=46777
}//先返回值,后修改
};
继承
继承的基本概念:

基类(Base Class):被继承的类,提供共有的属性和方法。
派生类(Derived Class):从基类继承的类,可以重用基类的成员,并且可以扩展或修改这些成员。
继承的类型
公有继承(Public Inheritance):

最常用的继承方式,表示派生类“是一个”基类的特殊类型。
基类的公有成员在派生类中保持公有,基类的保护成员在派生类中保持保护。
基类的私有成员不能直接访问。

class Base {
public:
int pubValue;
protected:
int protValue;
private:
int privValue;
};

class Derived : public Base {
public:
void accessMembers() {
pubValue = 1; // 可以访问公有成员
protValue = 2; // 可以访问保护成员
// privValue = 3; // 不能访问私有成员

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/866465.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

南京芯麒电子-基于6U VPX的TMS320C6678+XCVU9P的高性能处理平台

概述 该平台是由16nm工艺的的XCUV9P FPGA和TI公司高性能数字信号处理器TMS320C6678构建的一款标准6U VPX高性能数据处理平台,VPX P1上定义4个x4 GTY,P2上1路PCIe x16接口、P3~P6上引出了大量GTY/GTH以及RS422/GPIO信号。板卡提供2个FMC+接口、可搭配我司各类FMC子卡使用,实现…

XTR105 XTR105UA/2K5规格书具有传感器激励和线性化的 4mA 至 20mA 电流变送器芯片

XTR105 是一款带有两个精准电流源的单片 4mA 至20mA、2 线制电流发送器。该器件在一个单集成电路上提供针对铂 RTD 温度传感器和桥、仪表放大器以及电流输出电路的完整电流激励。多用途线性化电流提供一个对 RTD 的第二阶修正,通常可以实现一个 40:1 的线性改进。仪器放大器增…

[rustGUI][iced]基于rust的GUI库iced(0.13)的部件学习(03):图像的导入、显示、调整(暨image部件的使用介绍)

前言 本文是关于iced库的部件介绍,iced库是基于rust的GUI库,作者自述是受Elm启发。 iced目前的版本是0.13.1,相较于此前的0.12版本,有较大改动。 本合集是基于新版本的关于分部件(widget)的使用介绍,包括源代码介绍、实例使用等。 环境配置 系统:window10 平台:visual…

PyTorch团队为TorchAO引入1-8比特量化,提升ARM平台性能

在深度学习模型部署和优化领域,计算效率与资源消耗的平衡一直是一个核心挑战。PyTorch团队针对这一问题推出了创新性的技术方案——在其原生低精度计算库TorchAO中引入低位运算符支持。这一技术突破不仅实现了1至8位精度的嵌入层权重量化,还支持了具有8位动态量化激活的线性运…

设计团队管理的关键因素:如何确保成员高效协作

一、设计团队的组织架构 一个高效的设计团队通常有一个明确的组织架构,合理的分工与协作关系能够最大程度地提高团队的工作效率。在设计团队的组织架构中,一般包括项目经理、设计师、协调员以及可能的开发人员和客户代表。 1.1 项目经理(PM) 项目经理是设计团队的核心角色之…

欧阳的2024年终总结,迷茫,重生与失业

前言 这是欧阳第一次写年终总结,今年发生的事情还挺多的值得写篇文章记录一下。立个flag,以后每年都写一篇年终总结文章,5年后35岁再来看这些文章不知道是什么感觉。今年发生的事情可以总结为三个词语:迷茫、重生、失业。 欧阳也在找工作,坐标成都求内推! 事件 今年发生的…

JS将docx转为html代码--Vue3(简易版)

这两天突然接了一个把节气文章转成html页面的需求,本来只是需要多按几下ctrl+c,ctrl+v能解决的事,但是想想后续一年24个节气,就做个自动转换的工具吧。由于做软件还涉及到其他语言和配置环境,所以还是选择了web。 首先创建一个vue3项目,我用的vite搭建的,不会的请自行移步…

大语言模型提示技巧(八)-防止胡说八道

自然语言往往充满歧义和模糊性,模型在学习时可能会产生误解或错误理解一些概念,导致生成不准确的信息。为了尽量减少这些问题,研究人员和工程师会使用更大规模、更多样化和更准确的训练数据,调整模型架构,以及使用更先进的训练技术。但是自然语言本身就是复杂且充满挑战的…

使用API方式远程调用ollama模型

在有GPU的环境启动一个ollama大模型,非常简单:注意,ollama启动时默认监听在127.0.0.1:11434上,可以通过配置OLLAMA_HOST环境变量修改 `export OLLAMA_HOST="0.0.0.0:11434" ollama serve& ollama run qwen2.5:7b-instruct`然后就可以在远端访问: `curl http…

JMeter——压力测试工具的安装

JMetere 简介 jmeter 是 apache 公司基于 java 开发的一款开源压力测试工具,体积小,功能全,使用方便,是一个比较轻量级的测试工具,使用起来非常简 单。 jmeter 是免安装的,拿到安装包之后直接解压就可以使用,同时它在 linux/windows/macos 上都可以使用。 前提 已安装和…

微软开源!Office 文档轻松转 Markdown!

MarkItDown —— 微软开源的 Python 工具,能够将多种常见的文件格式(如 PDF、PowerPoint、Word、Excel、图像、音频和 HTML 等)转换为 Markdown 格式。大家好,我是 Java陈序员。 今天,给大家介绍一款微软开源的文档转 Markdown 工具。关注微信公众号:【Java陈序员】,获取…

人工智能(AI)在医学领域的应用 -九五小庞

人工智能(AI)在医学领域的应用是当前科技发展的重要方向之一,它通过提高医疗效率、准确性和个性化治疗水平,极大地改善了医疗服务的质量和患者的体验。以下是一些AI在医学领域的主要应用:辅助诊断医学影像分析:AI可以通过深度学习算法快速准确地分析CT、MRI、X光等医学影…