七、类的组合

1、组合

前面一直都在用组合的方法创造类。

class Circle
{
private:
    float radius;
public:
    Circle(float r);
    ~Circle();
    float circumference();
    float area();
};

如上面所示程序,Circle类中,也包含这float类型的数据。我们已经习惯于将C++的基本类型数据类型作为类的组成部件。实际上类的成员数据既可以是基本类型也可以是自定义类型,当然也可以是类的对象。

类的组合描述的就是一个类内嵌套其他类的对象作为成员的情况。它们之间的关系是一种包含与被包含的关系。

1.1 类的组合的构造函数

想象一下,如果一个类的定义中不含类的对象,只有基本数据类型那么参数的初始化就比较简单。如果类的数据中包含了自定义数据类型或者对象,那么我们在创建这个类的时候既要对本类的基本数据类型进行初始化,又要对内嵌对象成员进行初始化。此时,构造函数的调用顺序就尤其重要。

组合类构造函数定义的一般顺序:
类型::类名(形参表):内前对象1(形参表),内嵌对象2(形参表),...
{类的初始化}

Circle::Circle(float r):radius(r) {}
  • 调用内嵌对象的构造函数,调用顺序按照内嵌对象在组合类中的定义顺序,与组合类构造函数初始化列表没有关系。
  • 执行本类构造函数的函数体。
  • 析构函数的调用执行顺序与构造函数的刚好相反。

2、前向引用声明

C++中变量都是先定义,在使用。同样滴,C++中类也是这样的。

  1. 类应该先声明,后使用
  2. 如果需要在某个类的声明之前,引用该类,则应该进行前向引用声明。
  3. 前向引用声明只为程序引入一个表示符,具体声明在其它地方。
class B;//前向引用声明
class A{
	public:
	void f(B b);
};
class B{
	public:
	void g(A a);
};

注意:

  • 在提供一个完整的类的声明之前,不能声明该类的对象,也不能在内联成员函数中使用类的对象。
  • 当使用前向引用声明时,只能使用被声明的符号,而不能设计类的任何细节。
class Fred;//前向引用声明
class Barney{
	Fred x; //错误:类Fred的声明尚不完善
};
class Fred{
	Barney y;
};

3、结构体

结构是C++从C语言继承过来的。唯一的区别是,结构体和类的默认访问控制属性不同。类的缺省类型为private;结构体的缺省类型为public。

4、联合体

联合体的全部数据成员共享同一组内存单元。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的C#黄历: ```csharp using System; public class ChineseCalendar { private static DateTime baseDate = new DateTime(1900, 1, 31); private static int[] lunarMonthDays = new int[] { 29, 30 }; private static string[] Gan = new string[] { "甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸" }; private static string[] Zhi = new string[] { "子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥" }; private static string[] LunarMonthNames = new string[] { "正", "二", "三", "四", "五", "六", "", "八", "九", "十", "十一", "十二" }; private static string[] LunarDayNames = new string[] { "初", "十", "廿", "三" }; public static string GetChineseCalendar(DateTime date) { //计算阳历日期到基准日期的天数 int offsetDays = (int)(date - baseDate).TotalDays; //计算从基准日期开始的农历年份 int year = 1900; int yearDays = GetLunarYearDays(year); while (offsetDays >= yearDays) { offsetDays -= yearDays; year++; yearDays = GetLunarYearDays(year); } //计算此农历年份中的农历月份和农历日 int month = 1; int leapMonth = GetLunarLeapMonth(year); int days = 0; while (month <= 12) { if (month == leapMonth + 1 && leapMonth > 0) { //闰月 days = GetLunarLeapMonthDays(year); } else { days = GetLunarMonthDays(year, month); } if (offsetDays < days) { break; } offsetDays -= days; month++; } //计算农历日 int day = offsetDays + 1; //组合农历年月日 string lunarYear = GetLunarYearName(year); string lunarMonth = LunarMonthNames[month - 1]; if (month == leapMonth + 1 && leapMonth > 0) { lunarMonth = "闰" + lunarMonth; } string lunarDay = GetLunarDayName(day); return lunarYear + "年" + lunarMonth + "月" + lunarDay + "日"; } //计算农历年份的天数 private static int GetLunarYearDays(int year) { int days = 0; for (int i = 0; i < 12; i++) { days += GetLunarMonthDays(year, i + 1); } return days; } //计算农历月份的天数 private static int GetLunarMonthDays(int year, int month) { int monthDays = (lunarMonthDays[(year - 1900) / 4] >> ((month - 1) * 2)) & 0x3; int leapMonth = GetLunarLeapMonth(year); if (month == leapMonth + 1 && leapMonth > 0) { //闰月 monthDays = GetLunarLeapMonthDays(year); } return monthDays; } //计算农历闰月的月份,返回0表示该年没有闰月 private static int GetLunarLeapMonth(int year) { int leapMonth = lunarMonthDays[(year - 1900) / 4] & 0xf; return leapMonth == 0xf ? 0 : leapMonth; } //计算农历闰月的天数 private static int GetLunarLeapMonthDays(int year) { int leapMonthDays = lunarMonthDays[(year - 1900) / 4] & 0x30; return leapMonthDays == 0x20 ? 29 : 30; } //获取农历年份的名称 private static string GetLunarYearName(int year) { int ganIndex = (year - 4) % 10; int zhiIndex = (year - 4) % 12; return Gan[ganIndex] + Zhi[zhiIndex]; } //获取农历日的名称 private static string GetLunarDayName(int day) { string dayName = ""; if (day == 20) { dayName = "二十"; } else if (day == 30) { dayName = "三十"; } else { int tens = day / 10; int ones = day % 10; dayName = LunarDayNames[tens - 1] + (ones == 0 ? "十" : LunarDayNames[1] + Zhi[ones - 1]); } return dayName; } } ``` 使用示例: ```csharp DateTime date = new DateTime(2022, 1, 1); string chineseCalendar = ChineseCalendar.GetChineseCalendar(date); Console.WriteLine(chineseCalendar); //输出"辛丑年正月初一" ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值