前言
本系列内容为程序媛学习C++时做的笔记。以代码为主,并备注了打印结果以及详尽的解释注释。希望对你有所帮助。
ps:如果没有C语言或C++的基础,建议从这篇文章看起。
命名空间:namespace
#include <iostream>
// 声明std,我们的main函数就可以直接使用里面的成员,不需要使用 std::
using namespace std;
namespace sun {
char *name;
void show() {}
namespace hl {//命名空间嵌套
void innerShow() {};
}
}
void test() {
sun::name;//不声明命名空间时,调用要加sun::
using namespace sun;//声明sun的命名空间
show();//可省略sun::
sun::hl::innerShow();//使用嵌套的命名空间
using namespace sun::hl;//声明嵌套的命名空间,调用就可省略sun::hl::
innerShow();
}
int main() {
cout << "使用cout,省略std::" << endl;
test();
return 0;
}
构造函数
AClass.h
#include <iostream>
using namespace std;
class AClass {
private:
int age;
char *name;
public:
void setAge(int age);
int getAge();
void setName(char *name);
char *getName();
//:AClass()是指:调用无参构造函数之前先调用两个参数的构造函数
AClass() : AClass(10, "sun") {//无参构造函数
cout << "无参构造函数" << endl;
}
//第1种构造函数声明的方式
AClass(char *name) {//一个参数的构造函数
this->name = name;
cout << "一个参数的构造函数" << endl;
}
//第2种构造函数声明的方式
//使用: age(age), name(name) ,会自动给age/name赋值
AClass(int age, char *name) : age(age), name(name) {//两个参数的构造函数
cout << "两个参数的构造函数" << endl;
}
};
AClass.cpp
#include "AClass.h"
void AClass::setAge(int age) {
AClass::age = age;
}
int AClass::getAge() {
return age;
}
void AClass::setName(char *name) {
this->name = name;
}
char *AClass::getName() {
return this->name;
}
调用:
int main() {
///创建AClass-----------------栈区开辟空间(不用手动释放空间)
//调用无参的构造函数
AClass a1; //打印:两个参数的构造函数 无参构造函数
//AClass a2();//不会调用构造函数
cout << "age:" << a1.getAge() << " name:" << a1.getName() << endl;//age:10 name:sun
//调用俩个参数的构造函数
AClass a3(18, "hl");//打印:两个参数的构造函数
cout << "age:" << a3.getAge() << " name:" << a3.getName() << endl;//age:18 name:hl
///创建AClass-----------------堆区开辟空间(堆区必须手动释放,否则内存占用越来越大)
AClass *a4 = new AClass();
cout << "age:" << a4->getAge() << " name:" << a4->getName() << endl;//age:10 name:sun
delete a4;//注意:调用delete释放,不是free。free和malloc是一对。
a4 = NULL;
return 0;
}
析构函数
AClass(char *name) {
this->name = (char *) malloc(sizeof(char *) * 10);
strcpy(this->name, "小妹"); //this->name="小妹";也可以
}
~AClass() {
// 临终遗言,AClass,你做一些释放工作。比如:上面调用malloc给name赋值。
// delete aClass 的时候,我们的析构函数一定执行;弹栈时,栈内的aClass也会调用析构。
// free不会执行析构函数,也意味着,你没法在析构函数里面,做释放工作;
// 而且用malloc创建AClass对象时,也不会调用构造函数
cout << "析构函数" << endl;
if (this->name) {//临终要做的事:
printf("~AClass:%s\n", this->name);
free(this->name);
this->name = NULL;
}
}
打印:
析构函数
~AClass:sun
析构函数
~AClass:hl
析构函数
~AClass:sun
拷贝构造函数
// 拷贝构造函数,它默认有,我们看不到,一旦我们写拷贝构造函数,会覆盖她
// 对象1 = 对象2
// 覆盖拷贝构造函数
AClass(const AClass &aClass) {// 常量引用:只读的,不让你修改
cout << "拷贝构造函数" << endl;
//this->name = aClass.name;//正常赋值
this->name = "拷贝name";//随意改值
}
调用:
AClass a1(1, "张三");
AClass a2 = a1;//这样赋值是会调用 自定义拷贝构造函数,我们自己赋值
cout << "a1 name:" << a1.getName() << " a2 name:" << a2.getName() << endl;
//a1 name:张三 a2 name:拷贝name
AClass a3;
a3 = a1;//这样赋值是不会调用 自定义拷贝构造函数,但是会调用默认赋值(隐式代码)
cout << "a3 name:" << a3.getName() << " a3 name:" << a3.getName() << endl;
//a3 name:张三 a3 name:张三
思考:下面这种写法,拷贝构造函数到底会不会调用?
AClass *a1 = new AClass(39, "杜子腾");
cout << a1->getAge() << endl; //39
AClass *a2 = a1; // 压根就不会执行拷贝构造函数(指针指向问题,和对象2=对象1是两回事)
a2->setAge(99); //a1,a2地址指向一样,改一个都会变。
cout << a1->getAge() << endl; //99
cout << a2->getName() << endl; //杜子腾
不会。
指针常量 常量指针 常量指针常量
int num = 1;
int num2 = 2;
//常量指针
const int *numP_1 = #
numP_1 = &num2;//允许重新指向【常量指针】存放的地址
*numP_1 = 100;//报错,不允许修改【常量指针】存放地址所对应的值
//指针常量
int *const numP_2 = #
numP_2 = &num2;//报错,不允许修改
*numP_2 = 100;
//常量指针常量
const int *const numP_3 = #
numP_3 = &num2;//报错,不允许修改
*numP_3 = 100;//报错,不允许修改
常量指针:常量的指针。常量不能修改,指针能修改。
指针常量:指针是个常量。指针不能修改,指针对应的值能修改。