C++常见用法
类
参数初始化
在类的使用中,在构造函数后初始化参数,可以给常量赋值。
const成员函数
不修改成员变量,const实例对象调用时,不会出现限制类型丢失错误。
class Test
{
public:
Test(): value(100) {}
~Test() {}
int get() const
{
return value;
}
private:
const int value;
};
int main()
{
const Test t;
printf("%d\n", t.get());
return 0;
}
如果int get() const 去掉const,会报错误
error: passing ‘const Test’’ as ‘this’ argument discards qualifiers [-fpermissive]
const指针
const * p和*const p,记忆方式:前者相当于const(*p),定值;后者相当于 *(const p),定项。
左定值,右定项
const &
引用可以修改,const &不可修改。
类回调
class caller
{
public:
caller() {}
virtual ~caller() {}
virtual int add(int x, int y) = 0;
private:
};
class invoker
{
public:
invoker(): mCaller(NULL) {}
~invoker() {}
void setCall(caller* p)
{
mCaller = p;
}
void fun()
{
int sum = mCaller->add(100,200);
printf("sum is %d\n", sum);
}
private:
caller *mCaller;
};
class child : public caller
{
public:
child() {}
~child() {}
int add(int x, int y)
{
return x + y;
}
private:
};
int main()
{
caller *p = new child();
invoker ivk;
ivk.setCall(p);
ivk.fun();
return 0;
}
通过继承接口类,在目标类中调用接口类子类中的方法。
(父类的析够函数一般要加上virtual,当父类指针指向子类时,在析够的时候能释放子类。)
类赋值和拷贝
这个在类中很重要,特别是在我们的类中有指针,存在内存申请和释放的情况下,我们要重写赋值和构造,保证数据能够被拷贝和赋值。
class CExample
{
public:
CExample() : data(NULL), size(0) {}
CExample(int size)
{
this->size = size;
data = (float *)malloc(this->size * sizeof(float));
}
~CExample()
{
if (data != NULL)
{
free(data);
data = NULL;
}
}
//拷贝构造函数
CExample(const CExample &t)
{
this->size = t.size;
data = (float *)malloc(this->size * sizeof(float));
memcpy(this->data, t.data, this->size * sizeof(float));
}
// 赋值
CExample &operator=(const CExample &t)
{
if (this != &t)
{
this->size = t.size;
data = (float *)malloc(this->size * sizeof(float));
memcpy(this->data, t.data, this->size * sizeof(float));
}
return *this;
}
void print()
{
for (int i = 0; i < this->size; i++)
{
printf("%f\t", data[i]);
}
printf("\n");
}
private:
float *data;
int size;
};
int main()
{
CExample obj;
CExample obj1(obj); // 调用拷贝构造函数
CExample obj2;
obj2 = obj; // 调用赋值函数
CExample obj3 = obj; // 调用拷贝构造函数,因为obj3还没有创建
return 0;
}
如果不重载拷贝构造和赋值函数,则data的数据并没有被拷贝,只是赋个指针,释放时也会出错。
回调函数
- 函数指针
typedef int (*callback)(int, int); // 使用typedef定义为一个类型,而不是对象
int (*cb)(int, int); // 不使用typedef定义,是函数指针
int add(int x, int y, callback p)
{
return (*p)(x, y);
}
int add(int x, int y)
{
return x + y;
}
int main()
{
cout << add(1000, 2000, add) << endl;
return 0;
}
- 函数模板
typedef std::function<int(int a, int b)> FunCallBack;
int add(int x, int y, FunCallBack &fp)
{
return fp(x, y);
}
int main()
{
FunCallBack cb = [&](int x, int y) { // lamada 表达式
return add(x, y);
};
cout << add(1000, 2000, cb) << endl;
return 0;
}
class构造和析够
#include <iostream>
using namespace std;
class A{
public:
A(){
cout << "Class A is constructed!" << endl;
}
~A(){
cout << "Class A is desconstructed!" << endl;
}
};
class B{
public:
B(){
cout << "Class B is constructed!" << endl;
}
~B(){
cout << "Class B is desconstructed!" << endl;
}
};
class C : public B{
public:
C() {
cout << "Class C is constructed!" << endl;
}
~C() {
cout << "Class C is desconstructed!" << endl;
}
private:
A a;
};
int main(){
C c;
return 0;
}
Class B is constructed!
Class A is constructed!
Class C is constructed!
Class C is desconstructed!
Class A is desconstructed!
Class B is desconstructed!
类析构顺序:1)派生类本身的析构函数;2)对象成员析构函数;3)基类析构函数。