结论:类中的初始化最好都使用成员初始化列表
成员初始化列表
成员初始化列表是一个很好用的东西,用在类的初始化函数当中
class Entity {
public:
int a;
int b;
int c;
Entity()
: a(1),b(2),c(3) //成员初始化列表
{
std::cout << a << b << c << std::endl;
}
};
int main() {
Entity test;
}
在一个类需要初始化很多变量时,你可以直接一行解决,十分方便。
为什么要使用成员初始化列表
#include <iostream>
#include <string>
class example {
public:
example() {
std::cout << "example created!" << std::endl;
}
example(int x) {
std::cout << "example created with " << x << std::endl;
}
};
class Entity {
public:
example e;
std::string m_string;
int a;
int b;
int c;
Entity()
: a(1),b(2),c(3)
{
e = example(8);
m_string = "hahah";
std::cout << a << b << c << std::endl;
}
};
int main() {
Entity test;
}
运行这段代码,我们发现 Entity类型中的example被初始化了2次(运行后发现打印了2输出函数)
而使用成员初始化列表则不会出现这种情况。
#include <iostream>
#include <string>
class example {
public:
example() {
std::cout << "example created!" << std::endl;
}
example(int x) {
std::cout << "example created with " << x << std::endl;
}
};
class Entity {
public:
example e;
std::string m_string;
int a;
int b;
int c;
Entity()
: a(1),b(2),c(3),e(8),m_string("hhh")
{
std::cout << a << b << c << std::endl;
}
};
int main() {
Entity test;
}
三元运算符
int a = 10;
int b = a > 10 ? 5 : 6;
就是一种三元运算符的使用方式,等价替换为:
int a = 10;
if(a>10){
b = 5;
}else{
b = 6;
}
用三元运算符可以减少代码行数,简化代码,但是尽量不要用三元运算符进行嵌套(固然代码很少,但是很搞人心态哈哈哈)
new/delete
new
和 delete
是c++中的用于在heap
上申请内存空间和释放空间的关键字。
直接上例子
#include <iostream>
#include <string>
int main() {
int* a = new int(5);
std::cout << *a << std::endl;
delete a;
int* b = new int[50];
delete[] b;
}
delete[]
用于当你申请的是一个数组时。
new/delete实际上做了什么
new实际上调用了malloc
函数,然后再调用类的构造函数。
delete实际上调用了类的析构函数,然后调用了free
函数
explict关键字
直接先来看代码
#include <iostream>
#include <string>
class Entity {
public:
std::string m_name;
int m_age;
Entity(const std::string &name)
:m_name(name),m_age(-1) {
}
Entity(int age)
:m_name("unknown"), m_age(age) {
}
};
void print_entity(Entity& entity) {
std::cout << entity.m_name << std::endl;
}
int main() {
Entity a = 22;//?神马东西
print_entity(a);
}
其实咱们可以发现,它还是能正常运行的。原因在于c++编译器自动对其做了隐式转换(implict convert
)
然后还有个问题
#include <iostream>
#include <string>
class Entity {
public:
std::string m_name;
int m_age;
Entity(const std::string &name)
:m_name(name),m_age(-1) {
}
Entity(int age)
:m_name("unknown"), m_age(age) {
}
};
void print_entity(Entity& entity) {
std::cout << entity.m_name << std::endl;
}
int main() {
Entity a = 22;
print_entity(a);
Entity b = "wsxk";//无法通过编译
print_entity(b);
}
implict convert
只能隐式转换一次,”wsxk”是一个const char *
类型,需要转变为std::string
类型,然后再转变为Entity
类型,其中隐式转换了2次,这是编译器不允许的.
如何避免意外的隐式转换
利用explict
关键字
#include <iostream>
#include <string>
class Entity {
public:
std::string m_name;
int m_age;
explicit Entity(const std::string &name)
:m_name(name),m_age(-1) {
}
explicit Entity(int age)
:m_name("unknown"), m_age(age) {
}
};
void print_entity(Entity& entity) {
std::cout << entity.m_name << std::endl;
}
int main() {
Entity a = 22; //报错
print_entity(a);
Entity b = "wsxk";//报错
print_entity(b);
}
operator
c++允许我们重新定义类中的一些运算符,例如+,-,*,/,==,!=
的行为,从而使得编写代码时变得简洁
#include <iostream>
class Vector {
public:
float x, y;
Vector(float a, float b):x(a),y(b) {}
Vector Add(const Vector& other) const {
return Vector(x + other.x, y + other.y);
}
Vector operator+(const Vector& ohter)const {
return Add(ohter);
}
Vector Multiply(const Vector& other) const {
return Vector(x * other.x, y * other.y);
}
Vector operator*(const Vector& other)const {
return Multiply(other);
}
bool equal(const Vector& other)const {
return x == other.x && y == other.y;
}
bool operator==(const Vector& other) const {
return equal(other);
}
};
int main() {
Vector position(1.0f, 2.0f);
Vector speed(1.1f, 1.1f);
Vector powerup(1.2f, 1.2f);
Vector result = position+speed*powerup;
std::cout << result.x << " " << result.y << std::endl;
if (position == speed) {
std::cout << "attack" << std::endl;
}
else {
std::cout << "miss" << std::endl;
}
}
值得注意的是,不应该重载过多的operator
this关键字
this关键字是类内部用于指向自身的指针
#include <iostream>
class Entity {
public:
int x, y;
Entity(int x, int y) {
this->x = x;
this->y = y;
}
};
int main() {
Entity a(3, 4);
std::cout << a.x << " " << a.y << std::endl;
}
可以方便的解决参数和变量重名的问题