C++ 聚合类(Aggregate Class)

C++ 聚合类(Aggregate Class)

概述

该篇文章是用于梳理在学习聚合类的相关文章过程中总结归纳的相关知识点。用于后续深入理解和使用聚合类进行准备。

聚合类定义

首先看一下C++标准中的定义:

An aggregate is an array or a class (clause 9) with no user-declared constructors (12.1), 
no private or protected non-static data members (clause 11), 
no base classes (clause 10), and no virtual functions (10.3).

由以上定义看出满足以下条件的类才可以称之为聚合类

  1. 无自定义构造函数;
  2. 非静态数据成员没有大括号或等号初始化器,即类内没有初始值;
  3. 无私有或保护的非静态成员;
  4. 无基类和虚函数。

下面我们举一个简单的例子进行说明:
我们可以提供一个花括号扩起来的成员初始值列表,并用它初始化聚合类的数据成员,初始值的顺序必须与声明的顺序一致,初始值列表的元素个数少于类的成员数量,则靠后的成员被值初始化。

struct Person
{
	std::string name;
	int height;
};

int main()
{
	Person person = {"xiaohong",10};
	std::cout << person.name<<" "<<person.height << std::endl;
	system("pause");
	return 0;
}

以下我们在例举一些典型的非聚合类和聚合类:

// 非聚合类
class NotAggregate1
{
  virtual void f() {} //定义了虚函数
};

class NotAggregate2
{
  int x; //定义了非静态的私有属性
};

class NotAggregate3
{
public:
  NotAggregate3(int) {} 自定义了构造函数
};

// 聚合类
class Aggregate1
{
public:
  NotAggregate1 member1;   //公共成员
  Aggregate1& operator=(Aggregate1 const & rhs) {/* */} //重载赋值运算符
private:
  void f() {} // 私有函数
};

聚合类的特性

聚合类的的主要特性是可以使用**{}**符号像数组一样进行初始化。
先从数据的初始化进行说明,数组初始化的形式如下:
Type array_name[n] = {a1, a2, …, am};

if (m == n)
	array_name的第i个元素由ai进行初始化
else if (m < n)
	前m个元素由1~m个a进行初始化,m-n个元素由'value-initialized'实现初始化
else if (m > n)
	编译器报错
else (类似数组定义形式: int a[] = {1, 2, 3};)
	数组的长度m = = n
value-initialized

下面解释一下什么是值初始化:
当一个标量类型(bool、int、char、double、pointers 等)的对象被值初始化时,这意味着它被初始化为 0 表示该类型(false 表示 bool,0.0 表示 double 等)。当具有用户声明的默认构造函数的类类型对象进行值初始化时,调用其默认构造函数。这个定义不精确,有点不正确,但它应该给你基本的概念。不能对引用进行值初始化。 例如,如果类没有合适的默认构造函数,则非聚合类的值初始化可能会失败。
下面例举一些典型例子,用于说明数组初始化:

class A
{
public:
  A(int) {} //无默认构造函数
};
class B
{
public:
  B() {} //默认构造函数
};
int main()
{
  A a1[3] = {A(2), A(1), A(14)}; //正常 n == m
  A a2[3] = {A(2)}; //错误 类A没有默认构造函数. 无法对a2[1]和a2[2]进行值初始化
  B b1[3] = {B()}; //正常 b1[1]和b1[2]可以通过默认构造函数进行值初始化
  int Array1[1000] = {0}; //所有元素初始化为0;
  int Array2[1000] = {1}; //第一个元素初始化为1,其它全部为0;
  bool Array3[1000] = {}; //所有的值被初始化为false
  int Array4[1000]; //没有初始化,数组元素都是不确定的值;
  int array[2] = {1, 2, 3, 4}; //错误, 初始化值个数大于数组长度
}
聚合类的初始化方法

现在让我们看看如何用大括号初始化聚合类。几乎和数组的值初始化相同的方式。我们将按照在类定义中出现的顺序初始化非静态数据成员(根据定义,它们都是公共的)。如果初始化器比成员少,则其余的都是值初始化的。如果初始值设定项少于成员数,则其余的都是值初始化的。如果无法对未显式初始化的成员之一进行值初始化(如数据类型不匹配),则会出现编译时错误。如果初始值设定项过多,我们也会收到编译时错误。
如下面代码中所示:

struct X
{
  int i1;
  int i2;
};
struct Y
{
  char c;
  X x;
  int i[2];
  float f; 
protected:
  static double d;
private:
  void g(){}      
}; 

Y y = {'a', {10, 20}, {20, 30}};

在上面的例子中y.c用’a’初始化,y.x.i1用10,y.x.i2用20,y.i[0]用20,y.i[1]用30和y.f是值初始化的,即用0.0初始化。 受保护的静态成员 d 根本没有初始化,因为它是静态的。

union(聚合)

聚合联合的不同之处在于,可以只用大括号初始化它们的第一个成员。如果在 C++ 方面足够先进,甚至可以考虑使用联合(它们的使用可能非常危险,必须仔细考虑。

总结

现在我们知道了聚合的特别之处,让我们尝试了解对类的限制; 也就是说,他们为什么在那里。 我们应该明白,带大括号的成员初始化意味着该类只不过是其成员的总和。如果存在用户定义的构造函数,则意味着用户需要做一些额外的工作来初始化成员,因此大括号初始化将是不正确的。如果存在虚函数,则意味着该类的对象(在大多数实现中)具有指向该类的所谓 vtable 的指针,该指针是在构造函数中设置的,因此大括号初始化是不够的。

  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
您可以使用聚合函数来对进行汇总。聚合函数通常用于计算数据的统计信息,例如总和、平均值、最大值和最小值等。在C++中,您可以使用STL(标准模板库)中的算法来实现这些聚合操作。 首先,您需要包含适当的头文件: ```cpp #include <algorithm> #include <numeric> #include <vector> ``` 然后,假设您有一个名为`Student`的,其中包含学生的姓名和分数: ```cpp class Student { public: std::string name; int score; Student(const std::string& n, int s) : name(n), score(s) {} }; ``` 接下来,您可以创建一个`std::vector<Student>`来存储学生对象,并使用聚合函数对其进行汇总。以下是几个示例: 1. 计算总分: ```cpp std::vector<Student> students; // 假设已经填充了学生数据 int totalScore = std::accumulate(students.begin(), students.end(), 0, [](int sum, const Student& student) { return sum + student.score; }); ``` 2. 计算平均分: ```cpp double averageScore = static_cast<double>(totalScore) / students.size(); ``` 3. 查找最高分和最低分: ```cpp auto minMaxScore = std::minmax_element(students.begin(), students.end(), [](const Student& student1, const Student& student2) { return student1.score < student2.score; }); int minScore = minMaxScore.first->score; int maxScore = minMaxScore.second->score; ``` 这只是聚合操作的一些示例,您还可以根据需求使用其他聚合函数和算法。希望这能帮助到您!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值