C++基础之常见问题
const相关问题
C++ 成员函数后面接 const
给隐含的this指针加const,表示这个this指向的东西是const的,也就是说这个函数中无法改动数据成员了,相当于只读操作
指向const对象的指针
形如 const double pi = 3.14;const double *cptr = π
指向const对象的指针 ***不允许修改所指的对象的值***
指向const对象的指针 强制要求也是const 例如 const double *cptr;
允许把非const对象的地址赋值给 指向const对象的指针
const指针
形如 int errNumb = 0;
int *const curErr = &errNumb;
const指针 一经定义不能再指向其他对象 ***可修改所指对象的值,取决于对象类型***
指向const对象的const指针
形如 const double PI =3.1415926;
const double *const pi_ptr = Π
指针既不可修改所指对象的值,也不可指向其他对象
指针和typedef
成员函数后面接:a(aa)
冒号后面跟的是赋值,这种写法是C++的特性。
A( int aa, int bb ):a(aa),b(bb)
aa赋给a bb赋给b
公有继承 保护继承 私有继承
派生类 公有继承 基类 基类的所有控制访问保持不变
保护继承 基类的公有继承变为保护继承
私有继承 基类的访问变为私有访问
纯虚函数 形如virtual void a = 0;派生类才可以重写
this 只能在非静态成员函数或非静态数据成员初始值设定项的内部引用 this只能用在类申明文件里面 不能实现和申明分开
基类的友元对从该基类派生的类型没有特殊访问权限,同样如果基类和派生类都需要访问另一个类,那么类必须特地将访问权限授予基类和每一个派生类
模板编写 头文件 要include 具体实现.cpp文件
使用new和不使用创建对象的区别
//普通创建对象 创建之时就自动分配内存 然后自动销毁 栈中分配
tQueue<int> t1;
t1.enqueue(1);
int out = t1.dequeue();
cout << out << endl;
//new创建对象 手动分配内存 手动销毁 不然内存泄露 堆中分配
tQueue<int> *ptr = new tQueue<int>();
ptr->enqueue(2);
int out2=ptr->dequeue();
cout << out2 << endl;
delete ptr;
cout不能使用string 需要将string转char * 解决办法:string.c_str()
template与template
1.template<typename T>与template<class T>一般情况下这两个通用,但有一个特例,就是当 T 是一个类,而这个类又有子类(假设名为 innerClass) 时,应 该用 template<typename>:
2.typename T::innerClass myInnerObject;这里的 typename 告诉编译器,T::innerClass 是一个类,程序要声明一个 T::innerClass 类的对象,而不是声明 T 的静态成员,而 typename 如果换成 class 则语法错误。
模板的特化
函数的特化 template<>
类的特化 成员函数不需要template
特化成员而不特化类
类模板的部分特化
泛型和模板的区别
1.泛型的具体类型的确定是在程序运行时,而模板的实例化是在编译时确定的;
2.泛型无特化(自定义实现特定类型的处理),模板特化可以针对特定类型处理;
3.泛型无部分特化,模板有;
4.模板支持模板类型的形参,虽然一般不那样做,泛型不可以。
模板是泛型的基础,泛型是对模板的推广。
强制类型转化
C++ 引入了四种功能不同的强制类型转换运算符以进行强制类型转换:static_cast、reinterpret_cast、const_cast 和 dynamic_cast
static_cast
static_cast 用于进行比较“自然”和低风险的转换,如整型和浮点型、字符型之间的互相转换。
另外,如果对象所属的类重载了强制类型转换运算符 T(如 T 是 int、int* 或其他类型名),则 static_cast 也能用来进行对象到 T 类型的转换。
static_cast 不能用于在不同类型的指针之间互相转换,也不能用于整型和指针之间的互相转换,当然也不能用于不同类型的引用之间的转换。因为这些属于风险比较高的转换。
reinterpret_cast
用于进行各种不同类型的指针之间、不同类型的引用之间以及指针和能容纳指针的整数类型之间的转换。转换时,执行的是逐个 比特复制 的操作。
这种转换提供了很强的灵活性,但转换的安全性只能由程序员的细心来保证了。例如,程序员执意要把一个 int* 指针、函数指针或其他类型的指针转换成 string* 类型的指针也是可以的,至于以后用转换后的指针调用 string 类的成员函数引发错误,程序员也只能自行承担查找错误的烦琐工作:(C++ 标准不允许将函数指针转换成对象指针,但有些编译器,如 Visual Studio 2010,则支持这种转换)
const_cast
const_cast 运算符仅用于进行去除 const 属性的转换
,它也是四个强制类型转换运算符中唯一能够去除 const 属性的运算符。
将 const 引用转换为同类型的非 const 引用,将 const 指针转换为同类型的非 const 指针时可以使用 const_cast 运算符。
dynamic_cast
用 reinterpret_cast 可以将多态基类(包含虚函数的基类)的指针强制转换为派生类的指针,但是这种转换不检查安全性,即不检查转换后的指针是否确实指向一个派生类对象。dynamic_cast 专门用于将多态基类的指针或引用强制转换为派生类的指针或引用,而且能够检查转换的安全性。对于不安全的指针转换,转换结果返回 NULL 指针。
dynamic_cast 是通过“运行时类型检查”
来保证安全性的。dynamic_cast 不能用于将非多态基类的指针或引用强制转换为派生类的指针或引用——这种转换没法保证安全性,只好用 reinterpret_cast 来完成。
虚继承
智能指针 解决对象需要手动delete问题 将对象托管给 shared_ptr
形如 shared_ptr<A> sp1(new A(2));
复制控制
野指针和内存泄露
malloc/free new/delete的区别
include ""和<>区别
仿函数
实现c++中string类 复制构造函数 赋值 复制 析构函数
入口函数 main wmain tmain
void main(int argc, char **argv)
argc 表示传参数个数 argv 命令行执行传入的参数 argv[0] 默认是exe路径 a[1-argc] 真正传参
int wmain(int argc, wchar_t** argv)
同理 只不过argv类型是宽字符