C++:对象数组、对象动态申请和释放、类的定义和实现分开、this指针、常成员函数、时钟
2017-02-02 21:32
1211 查看
一、对象数组的定义和初始化
1. 对象数组的创建方法: //常量都是无名对象
1)类类型 数组名[元素个数];
2)类类型 数组名[元素个数] = { 数组的初始化列表... };
2. 说明:
1)在没有初始化列表的数组中,所有对象默认调用无参的构造函数。
2)对于有初始化列表的数组中,可以用构造函数来生成"类类型"的无名对象来初始化数组内的元素。
二、对象的动态申请和释放
1. new/delete 来申请和释放单个对象
1)new 类类型
2)new 类类型(实参表)
2. new[]/delete[] 来动态创建对象数组
new 类名[元素个数];
说明:new[] 只能以无参形势调用相应的构造函数
3. new 和 malloc 区别
malloc之分配内存空间,new 做了两件事:
1)用malloc分配内存空间 //malloc是由系统来提供和分配的
2)调用构造函数来初始化这个空间所存放的对象
【练习:实现一个电子始终类 Clock类】
#include <time.h>
time_t time(time_t *t);
//time_t (unsigned long long) 返回 1970-01-01 00:00:00 至今的秒数
将time_t转换为年月日十分秒的方法:
time_t tt = time(NULL);
struct tm *p = localtime( &tt ); //&tt是地址
p->tm_hour; //小时,整型值
p->tm_min; //分钟,整型值
p->tm_sec; //秒,整型值
time_t tt = time(0); struct tm *time = localtime(&tt);
printf("%4d-%02d-%02d\n", time->tm_year+1900,time->tm_mon+1,time->tm_mday); //打印年月日
class Clock {
public:
void run() {
//循环
while(1) {
//打印当前的时间 00:00:00
sleep(1);
//将second成员加1秒
}
}
成员:小时hour、分钟minute、秒second
}
int main(void) {
Clock c( time(NULL) );
//time(NULL) 设置时钟的起始时间
c.run(); //让时间运行
return 0;
}
三、类的定义和实现分开
1. 成员函数的实现有两种方式:
1)类内声明,类内实现
2)类内声明,类外实现 /** 代码演示如下 **/
类内声明的方法不变;
类外实现的时候,"函数名前要加作用域的限定"。
如果函数形参表带有缺省实参,只能保留一个地方带有缺省实参,建议:将"缺省实参写在声明的地方"。
3)实现和声明分开:
时钟例子:"多文件编程"
clock.cpp //类的实现 #include "clock.h"
clock.h
//类的声明、头文件声明、条件编译
main.cpp (主函数) // #include "clock.h"
$: ls
clock.cpp clock.h main.cpp
$: g++ clock.cpp main.cpp -o myclock
$: myclock
16 : 38 : 43
四、this 指针
1. 在类内总有一个已定义的指针 this ,在成员函数调用时,this 指向调用这个函数的对象。
2. 作用:
1)用来区分一个对象内"标识符"的作用域;
2)成员函数可以用 this 返回调用对象的地址;
3)成员函数可以用 this 返回调用对象自身的引用;
4)成员函数可以用 this 指针来销毁自身;
3. 说明:
1)this 只能在成员函数内调用;
2)在C++编译器中只有一个 this 哪个对象在调用成员函数时,这个 this 就指向那个对象;
3)this 不占用对象的存储空间。
五、常成员函数
1. 常成员函数的语法形式:
类型 成员函数名 (形参表) [ const ] [ throw 列表 ] { ... }
具有 const 修饰的成员函数叫"常成员函数"。
2. 作用:
1)一个有常属性的对象只能调用常成员函数;
2)一个常成员函数不能修改对象内的成员,否则报错。"只读"
3. 说明:
1)具有常属性的对象只能调用常成员函数;
2)没有常属性的对象可以调用常成员函数,也能够调用普通成员函数,但会优先调用普通成员函数;
3)有常属性的成员函数与普通成员函数可以构成重载;
4)常成员函数不能修改对象自身的成员;
5)常成员函数不能返回非 const 属性的成员的引用(包括指针);
六、 mutable 关键字(变化的)
在具有常属性的成员函数中,不能修改成员对象的值,但有 mutable 修饰的成员对象除外。
作业:
写过的时钟类,改为定时器,进行定时后,在时间到来时,做相应的事儿。
1. 对象数组的创建方法: //常量都是无名对象
1)类类型 数组名[元素个数];
2)类类型 数组名[元素个数] = { 数组的初始化列表... };
2. 说明:
1)在没有初始化列表的数组中,所有对象默认调用无参的构造函数。
2)对于有初始化列表的数组中,可以用构造函数来生成"类类型"的无名对象来初始化数组内的元素。
/** 代码演示 **/ #include <iostream> using namespace std; class Student { public: Student(const string & n = "无名", double s = 0.0) : name(n), score(s) { } void printInfo() { cout << "我叫" << name << ",我的成绩" << score << endl; } private: string name; double score; }; int main(void) { //int arr2[3] = {1, 2}; Student arr2[3] = {Student(), Student("赵云", 97)}; for(int i = 0; i < 3; i++) { arr2[i].printInfo(); } cout << "------------" << endl; //int arr[10]; //等同如下 Student arr[10]; for(int i = 0; i < 10; i++) { arr[i].printInfo(); } return 0; }
二、对象的动态申请和释放
1. new/delete 来申请和释放单个对象
1)new 类类型
2)new 类类型(实参表)
2. new[]/delete[] 来动态创建对象数组
new 类名[元素个数];
说明:new[] 只能以无参形势调用相应的构造函数
3. new 和 malloc 区别
malloc之分配内存空间,new 做了两件事:
1)用malloc分配内存空间 //malloc是由系统来提供和分配的
2)调用构造函数来初始化这个空间所存放的对象
/** 代码演示 **/ #include <iostream> using namespace std; class Student { public: Student(const string & n = "无名", double s = 0.0) : name(n), score(s) { } void printInfo() { cout << "我叫" << name << ",我的成绩" << score << endl; } void setNameScore(const string & n, const double s) { name = n; if(s < 0 || s > 100.0) //数据校验,保证数据安全 return ; score = s; } private: string name; double score; }; int main(void) { Student * ps = new Student; ps->printInfo(); delete ps; ps = new Student("张飞", 60); ps->printInfo(); delete ps; //以下创建动态对象数组 ps = new Student[3]; //创建的时候不能初始化,C11可初始化(不常用) ps[0] = Student("张飞", 60); ps[1].setNameScore("关羽", 70); ps[2] = Student("刘备", 80); for(int i = 0; i < 3; i++) { ps[i].printInfo(); } delete[] ps; ps = NULL; return 0; }
【练习:实现一个电子始终类 Clock类】
#include <time.h>
time_t time(time_t *t);
//time_t (unsigned long long) 返回 1970-01-01 00:00:00 至今的秒数
将time_t转换为年月日十分秒的方法:
time_t tt = time(NULL);
struct tm *p = localtime( &tt ); //&tt是地址
p->tm_hour; //小时,整型值
p->tm_min; //分钟,整型值
p->tm_sec; //秒,整型值
time_t tt = time(0); struct tm *time = localtime(&tt);
printf("%4d-%02d-%02d\n", time->tm_year+1900,time->tm_mon+1,time->tm_mday); //打印年月日
class Clock {
public:
void run() {
//循环
while(1) {
//打印当前的时间 00:00:00
sleep(1);
//将second成员加1秒
}
}
成员:小时hour、分钟minute、秒second
}
int main(void) {
Clock c( time(NULL) );
//time(NULL) 设置时钟的起始时间
c.run(); //让时间运行
return 0;
}
/** 代码演示 - teacher **/ #include <stdio.h> using namespace std; class Clock { public: Clock(time_t tt = 0) { //1970-01-01 00:00:00 struct tm *p = localtime(&tt); hour = p->tm_hour; minute = p->tm_min; second = p->tm_sec; } void run() { while(1) { showTime();//显示时间 tick(); //滴答,时间+1s } } private: void tick() { sleep(1); ++second; //时间校正算法: minute += second/60; //0 or 1 second %= 60;//second不超过60 hour += minute/60;//0 or 1 minute %= 60;//minute不超过60 hour %= 24;//hour不超过24 } void showTime() { printf("\r%02d : %02d : %02d", hour, minute, second); fflush(stdout); } private: short hour; short minute; short second; }; int main(void) { Clock c(time(NULL)); c.run(); return 0; }
三、类的定义和实现分开
1. 成员函数的实现有两种方式:
1)类内声明,类内实现
2)类内声明,类外实现 /** 代码演示如下 **/
类内声明的方法不变;
类外实现的时候,"函数名前要加作用域的限定"。
如果函数形参表带有缺省实参,只能保留一个地方带有缺省实参,建议:将"缺省实参写在声明的地方"。
3)实现和声明分开:
时钟例子:"多文件编程"
clock.cpp //类的实现 #include "clock.h"
clock.h
//类的声明、头文件声明、条件编译
main.cpp (主函数) // #include "clock.h"
$: ls
clock.cpp clock.h main.cpp
$: g++ clock.cpp main.cpp -o myclock
$: myclock
16 : 38 : 43
/** 三、1. 2)类内声明,类外实现 **/ #include <iostream> #include <time.h> #include <stdio.h> using namespace std; class Clock { public: Clock(time_t tt = 0); void run(); private: void showTime(); void tick(); private: short hour; short minute; short second; }; Clock::Clock(time_t tt) { //类外声明不能加默认实参 struct tm *p = localtime(&tt); hour = p->tm_hour; minute = p->tm_min; second = p->tm_sec; } void Clock::run() { //在函数名前加作用域限定符 while(1) { showTime(); tick(); } } void Clock::tick() { sleep(1); ++second; minute += second/60; second %= 60; hour += minute/60; minute %= 60; hour %= 24; } void Clock::showTime() { printf("\r%02d : %02d : %02d", hour, minute, second); fflush(stdout); } int main(void) { Clock c(time(NULL)); c.run(); return 0; }
四、this 指针
1. 在类内总有一个已定义的指针 this ,在成员函数调用时,this 指向调用这个函数的对象。
2. 作用:
1)用来区分一个对象内"标识符"的作用域;
2)成员函数可以用 this 返回调用对象的地址;
3)成员函数可以用 this 返回调用对象自身的引用;
4)成员函数可以用 this 指针来销毁自身;
3. 说明:
1)this 只能在成员函数内调用;
2)在C++编译器中只有一个 this 哪个对象在调用成员函数时,这个 this 就指向那个对象;
3)this 不占用对象的存储空间。
/** 代码演示 **/ #include <iostream> using namespace std; class Teacher { public: Teacher(string name, int a) { this->name = name; //this不占用对象的空间,1)区分标识符作用域 age = a; cout << "Teacher() this =" << this << endl; } void printInfo() { cout << "printInfo() this =" << this << endl; cout << "我叫" << name << ",今年" << age << "。\n"; } Teacher * getMySelf() { return this; } //2)返回调用对象地址 Teacher & getSelf() { return *this; } //3)返回调用对象的引用 void freeSelf() { cout << "delete " << this << endl; delete this; } //4)销毁自身 private: string name; //封装了指针,4个字节 int age; //4个字节 }; int main(void) { Teacher t1("老魏", 40); t1.printInfo(); cout << "&t1 = " << &t1 << endl; cout << "t1.getMySelf() = " << t1.getMySelf() << endl; Teacher & rt1 = t1.getSelf(); rt1.printInfo(); //4)以下示意对象销毁自身 Teacher *p = new Teacher("孔明", 40); cout << "p = " << p << endl; p->freeSelf(); cout << "---------------------" << endl; Teacher t2("老王", 30); t2.printInfo(); cout << "&t2 = " << &t2 << endl; cout << "sizeof(t1)" << sizeof(t1) << endl;//8 return 0; }
五、常成员函数
1. 常成员函数的语法形式:
类型 成员函数名 (形参表) [ const ] [ throw 列表 ] { ... }
具有 const 修饰的成员函数叫"常成员函数"。
2. 作用:
1)一个有常属性的对象只能调用常成员函数;
2)一个常成员函数不能修改对象内的成员,否则报错。"只读"
3. 说明:
1)具有常属性的对象只能调用常成员函数;
2)没有常属性的对象可以调用常成员函数,也能够调用普通成员函数,但会优先调用普通成员函数;
3)有常属性的成员函数与普通成员函数可以构成重载;
4)常成员函数不能修改对象自身的成员;
5)常成员函数不能返回非 const 属性的成员的引用(包括指针);
/** 代码演示 **/ #include <iostream> using namespace std; class Person { public: Person(const string & n): name(n) {} void printInfo() { //重载,优先普通成员函数 cout << "我是普通的" << name << endl; } void printInfo() const { cout << "const我叫" << name << endl; } const string & getName() const { return name; } void setName(const string & n) { name = n; } private: string name; }; int main(void) { const Person p("小张"); p.printInfo(); // p.setName("张飞"); //出错,因为p为常对象 Person p2("小李"); p2.setName("李某某"); p2.printInfo(); const string & alias = p.getName(); // alias = "李四"; p2.printInfo(); return 0; }
六、 mutable 关键字(变化的)
在具有常属性的成员函数中,不能修改成员对象的值,但有 mutable 修饰的成员对象除外。
/** 代码演示 **/ class Person { public: Person(const string & n): name(n), count(0) {} private: string name; mutable int count; //不受成员函数const限定符的限制 }; int main(void) { const Person p("小张"); p.printInfo(); const string & alias = p.getName(); alias = "小李"; //报错!!! p.printInfo(); return 0; }
作业:
写过的时钟类,改为定时器,进行定时后,在时间到来时,做相应的事儿。
/** 【时钟案例】增加代码 **/ void Clock::alarmRun(short h, short m, short s) { while(1) { showTime(); if(hour == h && minute == m && second == s) { doSomething(); return; } tick(); } } void Clock::doSomething() { cout << "时间到了,起床!\n"; } #include "clock.h" int main(void) { Clock c(time(NULL)); // c.run(); c.alarmRun(10, 31, 0); return 0; }
相关文章推荐
- [C++学习笔记14]动态创建对象(定义静态方法实现在map查找具体类名对应的创建函数,并返回函数指针,map真是一个万能类)good
- C/C++动态内存分配之用malloc和指针实现动态数组排序
- c++之this指针做参数实现对象间的交互实例
- new、delete、指向连续空间的指针、数组、空间释放、空间申请[C++][内存管理]
- C++ 实现动态定义三维内的数组
- C++ 实现动态定义三维内的数组
- C++ 实现动态定义三维内的数组
- C++学习笔记(六)-- 类和对象 构造函数和析构函数 const成员函数 this指针 对象数组 堆栈管理变量
- new、delete、指向连续空间的指针、数组、空间释放、空间申请[C++][内存管理]
- C++ 常成员函数和常对象以及this指针的重要理解
- C++如何实现只能动态分配类对象,不能定义类对象
- c++对象数组和this指针
- new、delete、指向连续空间的指针、数组、空间释放、空间申请[C++][内存管理]
- C++:对象数组与this指针
- 走进C++程序世界-----指针(动态申请空间和释放空间)
- 不可或缺 Windows Native (18) - C++: this 指针, 对象数组, 对象和指针, const 对象, const 指针和指向 const 对象的指针, const 对象的引用
- C语言 指针相关问题--调用函数实现空间动态申请
- new、delete、指向连续空间的指针、数组、空间释放、空间申请
- C++多态中的实现要用指针,而不是虚基类(接口)的对象
- C/C++语言实现动态数组