返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C++类和对象补充
  • 180
分享到

C++类和对象补充

2024-04-02 19:04:59 180人浏览 泡泡鱼
摘要

目录一. 再看构造函数1.函数体内赋初值2.初始化列表几点注意3.explicit关键字二.static成员1.概念2.特性三.友元1.友元函数2.友元类四.内部类总结一. 再看构造

一. 再看构造函数

我们之前已经了解了构造函数的基本内容,那么这里我们将深入认识构造函数。

1.函数体内赋初值


class Date
{
public:
 Date(int year, int month, int day)
 {
 _year = year;
 _month = month;
 _day = day;
 //可以进行多次赋值,但一般不这么做
 _year = 1;
 }
private:
 int _year;
 int _month;
 int _day;
};

首先,对于构造函数体内的赋值我们不能称之为初始化。首先我们要理解:初始化只能初始化一次,而构造函数体内可以多次赋值。那么对象成员变量的初始化是在什么时候进行的呢?这就要接下来要介绍的初始化列表要做的事了。

2.初始化列表

初始化列表是以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面跟一个放在括号中的初始值或表达式。其形式如下:


class Date
{
public:
	Date(int year = 0, int month = 1, int day = 1)
		:_year(year)
		,_month(month)
	{
		_day = day;
	}
private:
	int _year;
	int _month;
	int _day;
};

几点注意

1.每个成员变量在初始化列表中只能出现一次(初始化只能初始化一次)

2.类中包含以下成员,必须放在初始化列表位置进行初始化:

(1)const成员变量:由于const变量初始化之后就不能更改,因此需在初始化列表进行初始化。

(2)引用成员变量:引用成员变量只能作为一个变量的引用,一旦初始化,就不能再作为其他变量的引用,因此引用变量也只能再初始化列表初始化。

(3)自定义类型成员变量(没有默认构造函数情况下):由于没有默认构造函数时,自定义类型变量是不能初始化的,此时程序也无法编译,因此没有默认构造函数的自定义类型成员变量必须在初始化列表进行初始化。


class B
{
public:
	B(int i)
		:_i(i)
	{
	}
private:
	int _i;
};
class A
{
public:
	A(int a, int& b, int bb)
		:_a(a)
		,_b(b)
		,_bb(bb)
	{
	}
private:
	const int _a;//const成员变量
	int& _b;//引用成员变量
	B _bb;//自定义成员变量
};

3.尽量使用初始化列表初始化,因为不管你是否使用初始化列表,对于自定义类型成员变量,一定会先使用初始化列表初始化。比如下面代码的执行结果:


class B
{
public:
	B()
	{
		cout << "B()" << endl;
	}
private:
	int _i;
};
class A
{
public:
	A(int a, int& b)
		:_a(a)
		,_b(b)
	{
	}
private:
	const int _a;//const成员变量
	int& _b;//引用成员变量
	B _bb;//自定义成员变量
};
int main()
{
	int n = 0;
	A a1(0, n);
	return 0;
}

在这里插入图片描述

可以看到,初始化列表中并没有对自定义变量_bb初始化,但程序仍然调用了自定义类型的默认构造函数。

4. 成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关,先想想下面的代码运行结果是什么:


class A
{
public:
	A(int a)
		:_a1(a)
		, _a2(_a1)
	{}
	void Print() {
		cout << _a1 << " " << _a2 << endl;
	}
private:
	int _a2;
	int _a1;
};
int main() 
{
	A aa(1);
	aa.Print();
	return 0;
}

在这里插入图片描述

可以看到的是,_a1为1,而_a2为随机值,这是因为在成员列表的声明中,_a2先被声明,_a1后被声明,因此初始化列表中的顺序是先_a2,后_a1。而一开始_a1为随机值,因此最终_a2为随机值。

3.explicit关键字

我们知道,对于构造函数,不仅可以构造和初始化对象,对于单个参数的构造函数,还具有类型转换的作用。

比如Date类:


class Date
{
public:
	Date(int year)
		:_year(year)
	{}
	explicit Date(int year)
		:_year(year)
	{}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date d1(2020);
	// 用一个整形变量给日期类型对象赋值
	// 实际编译器背后会用2019构造一个无名对象,最后用无名对象给d1对象进行赋值
	Date d2 = 2021;//explict禁止隐式类型转换,因此该句代码运行错误
}

但是Date d2 = 2021;这样的代码可读性不是很好,因此可以使用explicit关键字将这种隐式类型转换禁止。

二.static成员

C语言中我们就接触了static关键字,那么这个关键字修饰成员会怎么样呢?

1.概念

声明为static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量;用static修饰的成员函数,称之为静态成员函数。像上面初始化列表中说的,静态的成员变量一定要在类外进行初始化。

2.特性

静态成员存储在静态区,为所有类对象所共享,不属于某个具体的实例

静态成员变量必须在类外定义,定义时不添加static关键字

类静态成员即可用类名::静态成员或者对象.静态成员来访问

静态成员函数没有隐藏的this指针,不能访问任何非静态成员;相对的,非静态成员函数可以通过this指针访问静态成员变量。

静态成员和类的普通成员一样,也有public、protected、private 3种访问级别,也可以具有返回值

接下来我们来看看一道题:

求1+2+3+…+n

题目描述:求1+2+3+…+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。
这道题我们可以利用构造函数,由于每次实例化对象,都会调用其构造函数,因此我们可以实例化n个对象,每次初始化时计算求和即可;


class Sum
{
public:
    //调用构造函数
    Sum()
    {
        _sum += _i;
        ++_i;
    }
    //static修饰的成员函数,没有隐含的this指针,只能访问静态成员变量
    static int GetSum()
    {
        return _sum;
    }
private:
	//static修饰的成员变量为所有定义出来的类对象共有
    static int _i;
    static int _sum;
};
//静态成员变量的定义
int Sum::_i = 1;
int Sum::_sum = 0;
class Solution {
public:
    int Sum_Solution(int n) {
        Sum* p = new Sum[n];
        return Sum::GetSum();
    }
};

【注意】sizeof(类名)不计算静态成员变量的大小。比如上述代码中的sizeof(Sum)为1,是一个空类。

三.友元

友元分为友元函数和友元类,其提供了一种突破封装的方式,有时提供了便利。但是友元会增加耦合度,破坏了封装,所以友元不宜多用。

1.友元函数

首先如果我们要重载<<(流插入)运算符,我们会发现将其定义成类成员函数将无法实现,这是因为类成员函数的第一个参数为this指针,那么我们只能将这个函数定义在类外,但是这样的话函数又不能访问类中的成员变量,那么这个时候要么在成员函数中实现访问的方法,要么就使用友元函数,使其可以访问类中成员。即:


class Date
{
	//用关键字friend在类中声明函数为Date的友元函数
	friend ostream& operator<<(ostream& out, const Date& d);
public:
	Date(int year, int month, int day)
		:_year(year)
		,_month(month)
		,_day(day)
	{}
private:
	int _year;
	int _month;
	int _day;
};
ostream& operator<<(ostream& out, const Date& d)
{
	out << d._year << "/" << d._month << "/" << d._day;
	return out;
}
int main()
{
	Date d1(2021, 10, 20);
	cout << d1 << endl;
}

同理,cin也可以如此定义。

【说明】

1.友元函数可访问类的私有和保护成员,但不是类的成员函数

2.友元函数不能用const修饰

3.友元函数可以在类定义的任何地方声明,不受类访问限定符限制

4.一个函数可以是多个类的友元函数

5.友元函数的调用与普通函数的调用和原理相同

2.友元类

和友元函数相似,友元类可以访问另一个类的私有成员。比如下面代码中,B作为A的友元类,可以访问A中的_a和_i。


class A
{
	//声明B为A的友元类,则在B中可以访问A中的成员
	friend class B;
public:
	A(int a)
		:_a(a)
	{
	}
private:
	int _a;
	static int _i;
};
class B
{
public:
	B(int b)
		:_b(b)
	{}
	static int Count()
	{
		A::_i++;
		return A::_i;
	}
private:
	int _b;
};
int A::_i = 0;
int main()
{
	A a1(1);
	B b1(1);
	cout << b1.Count() << endl;
	cout << b1.Count() << endl;
	return 0;
}

需要注意,友元关系是单向的,不具有交换性,比如上述代码中A不能访问B中的成员;友元关系不能传递,即B是A的友元,C是B的友元,但C不是A的友元,C就不能访问A中的私有成员。

四.内部类

顾名思义,定义在另一个类中的类就是内部类。注意此时这个内部类是一个独立的类,它不属于外部类,更不能通过外部类的对象去调用内部类。外部类对内部类没有任何优越的访问权限。

内部类就是外部类的友元类。注意友元类的定义,内部类可以通过外部类的对象参数来访问外部类中的所有成员。但是外部类不是内部类的友元。


class A
{
public:
	class B//内部类,是A的友元类
	{
	public:
	//B可以直接访问A的成员
		void Print(const A& a)
		{
			cout << a._a << endl;
			cout << _i << endl;
		}
	};
	A(int a)
		:_a(a)
	{}
private:
	int _a;
	static int _i;
};
int main()
{
	A::B b1;//注意B的调用方式
	A a1(1);
	b1.Print(a1);
	//但A的对象不能去访问B中的成员
	a1.b1;//error
}

特性:

1.内部类可以定义在外部类的public、protected、private都是可以的。

2.注意内部类可以直接访问外部类中的static、枚举成员,不需要外部类的对象/类名。

3.sizeof(外部类)=外部类,和内部类没有任何关系。比如上面的sizeof(A)为4。

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注编程网的更多内容!

--结束END--

本文标题: C++类和对象补充

本文链接: https://lsjlt.com/news/155098.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • C++类和对象补充
    目录一. 再看构造函数1.函数体内赋初值2.初始化列表几点注意3.explicit关键字二.static成员1.概念2.特性三.友元1.友元函数2.友元类四.内部类总结一. 再看构造...
    99+
    2024-04-02
  • 【C++】类和对象(四)
    1.初始化列表: 1.1为什么要有初始化列表? 实验代码如下: class A{public: int _a1;//声明 int _a2; const int _x;};int main(){ A aa;//...
    99+
    2023-08-30
    c++ java 算法
  • 【C++】类和对象(三)
    类和对象(三) 拷贝构造函数: 当我们想要将一个已确定的类变量的值拷贝给另外一个相同类型的类变量,有什么快捷的方法吗? 就相当于定义了一个int类型的i=10,想将i复制给一个刚初始化的遍历j,int...
    99+
    2023-08-31
    c++ java 开发语言
  • C++初识类和对象
    目录一.初步认识面向过程和面向对象二.类的引入三.类的定义1.定义和声明全部放在类体中,需要注意的是:2.声明与定义分离四.类的访问限定符及封装1.访问限定符2.封装五.类的作用域六...
    99+
    2024-04-02
  • C++ 再识类和对象
    目录类的6个默认成员函数构造函数1.概念2.特性隐式构造函数无参和全缺省的函数均为默认构造函数成员变量的命名风格补充析构函数1.概念2.特性c++编译器在对象生命周期结束时自动调用析...
    99+
    2024-04-02
  • C++类和对象基础详解
    目录一、类和对象的基本概念结构化程序设计面向对象的程序设计使用类的成员变量和成员函数二、类和对象基础 类成员的可访问范围构造函数(constructor)基本概念拷贝(复制)构造函数...
    99+
    2024-04-02
  • 关于C# 类和对象详情
    目录一、对象的定义和创建二、、对象的初始化1. 借助构造函数或使用2. 实例构造函数3. 静态构造三、对象的引用一、对象的定义和创建 定义类对象的方法为: 类名 对象名; 类是...
    99+
    2024-04-02
  • C++中类和对象是什么
    这篇文章给大家分享的是有关C++中类和对象是什么的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。类和对象<上>面向对象一直以来都是面向过程编程比如C语言,直到七十年代面向过程编程在开发大型程序时表现出不...
    99+
    2023-06-29
  • c++类和对象基本概念
    目录什么是类?什么是对象?类的定义创建对象成员访问(初始化)总结什么是类? 一系列事物的抽象,对于c++而言,万事万物都可以是类。 类包括:属性+行为 属性:事物特征->数据类...
    99+
    2024-04-02
  • 详解C++之类和对象(2)
    目录一.构造函数1.构造函数的定义:2.构造函数的特征:3.构造函数的实现:3.1.系统默认的构造函数3.2无参构造3.3 带参构造二 析构函数1.析构函数的定义2.析构函数的特征三...
    99+
    2024-04-02
  • 详解C++之类和对象(1)
    目录C语言和C++的一大区别struct和class的区别总结c++类的由来(或者说为什么要增加类):我们知道c语言是面向过程的语言,c++是即面向过程又是面向过程的语言。那么这两个...
    99+
    2024-04-02
  • c++中对象和类的关系
    在 c++ 中,对象是类的具体实例,类是对象蓝图。对象拥有类的特性(数据成员)和行为(成员函数),而类定义对象的特性和行为规范。对象通过类创建,使用类成员函数访问特性和行为,而类则不能直...
    99+
    2024-05-10
    c++
  • c++中类和对象的关系
    类定义数据和操作,而对象是类的具体实例,包含并执行这些数据和操作。类提供通用模板,对象是模板的实现;类定义属性和行为,对象存储数据值并执行行为;类是静态的,对象是动态的;对象实例化自类,...
    99+
    2024-05-08
    c++
  • c++中类和对象的区别
    类是创建对象的模板,而对象是类的实例。主要区别包括:抽象与具体:类是抽象实体,对象是具体实例。数据封装:类定义数据结构和访问权限,对象包含实际数据值。行为封装:类定义方法,对象可执行这些...
    99+
    2024-05-08
    c++
  • C++初阶教程之类和对象
    目录类和对象<上>1. 类的定义2. 类的封装2.1 访问限定修饰符2.2 类的封装3. 类的使用3.1 类的作用域3.2 类的实例化4. 类对象的存储5. this 指...
    99+
    2024-04-02
  • C++类和对象到底是什么
    目录1、C++ 中的类2、面向对象编程(Object Oriented Programming,OOP)1、C++ 中的类 C++ 中的类(Class)可以看做C语言中结构体(Str...
    99+
    2024-04-02
  • C++入门浅谈之类和对象
    目录一、面向过程vs面向对象二、类的限定符及封装三、类的实例化四、this指针五、默认成员函数1. 构造函数2. 析构函数3. 拷贝函数4. 赋值运算符重载总结一、面向过程vs面向对...
    99+
    2024-04-02
  • C++类和对象之封装详解
    目录封装的意义以及示例访问权限公共权限 public保护权限 protected私有权限 privatestruct 和 class的区别成员属性私有化案例1:设计立方体类案例2:点...
    99+
    2024-04-02
  • C++类和对象之多态详解
    目录多态基本概念和原理剖析多态案例1 计算器类纯虚函数和抽象类多态案例2 制作饮品虚析构和纯虚析构多态案例3 电脑组装多态基本概念和原理剖析 多态:多态是C++面向对象的三大特性之一...
    99+
    2024-04-02
  • C++中怎么创建类和对象
    在C++中,可以通过关键字class来创建类,通过关键字new来创建对象。 以下是一个简单的示例: #include <ios...
    99+
    2024-03-11
    C++
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作