#include
#include
using namespace std;
//类型转换
void Insert(size_t pos, char ch)
{
size_t _size = 5;
//....
int end = _size - 1;
while (end >= pos) // end隐式类型转换
{
//_str[end + 1] = _str[end];
--end;
}
}
void Test1()
{
int i = 1;
// 隐式类型转换(意义相近的类型)
double d = i;
printf("%d, %.2f\n", i, d);
int* p = &i;
// 显示的强制类型转换(意义不相近的类型,值转换后有意义)
int address = (int)p;
printf("%x, %d\n", p, address);
Insert(3, 'a');
Insert(0, 'a');
}
int main()
{
Test1();
return 0;
}
是会有一点问题的。
int main()
{
double d = 12.34;
int a = static_cast(d);
cout << a << endl;
int* p = &a;
// 不支持的
//int address = static_cast(p);
int address = reinterpret_cast(p);
return 0;
}
int main()
{
const int a = 2;
int* p = const_cast(&a);
*p = 3;
cout << a << endl;
cout << *p << endl;
return 0;
}
这是控制台结果,我们还可以看一下监视和反汇编
从反汇编我们可以看到a直接呗替换成了常量 2
监视窗口下我们发现 a和*p的值都是2
这都源于编译器对代码进行的优化
我们通过添加volatile关键字来取消这种优化
int main()
{
/*const int a = 2;*/
volatile const int a = 2;
int* p = const_cast(&a);
*p = 3;
cout << a << endl;
cout << *p << endl;
return 0;
}
class A
{
public:
virtual void f(){}
public:
int _a = 0;
};
class B : public A
{
public:
int _b = 1;
};
// A*指针pa有可能指向父类,有可能指向子类
void fun(A* pa)
{
// 如果pa是指向子类,那么可以转换,转换表达式返回正确的地址
// 如果pa是指向父类,那么不能转换,转换表达式返回nullptr
B* pb = dynamic_cast(pa); // 安全的
//B* pb = (B*)pa; // 不安全
if (pb)
{
cout << "转换成功" << endl;
pb->_a++;
pb->_b++;
cout << pb->_a << ":" << pb->_b << endl;
}
else
{
cout << "转换失败" << endl;
pa->_a++;
cout << pa->_a << endl;
}
}
int main()
{
A aa;
// 父类对象无论如何都是不允许转换成子类对象的
/*B bb = dynamic_cast(aa);
B bb = (B)aa;*/
B bb;
fun(&aa);
fun(&bb);
//fun(nullptr);
return 0;
}
C的这种用法hi能出结果,(运行不会被中断的)
class A1
{
public:
//virtual void f(){}
public:
int _a1 = 0;
};
class A2
{
public:
//virtual void f(){}
public:
int _a2 = 0;
};
class B : public A1, public A2//多继承
{
public:
int _b = 1;
};
int main()
{
B bb;
A1* ptr1 = &bb;
A2* ptr2 = &bb;
cout << ptr1 << endl;
cout << ptr2 << endl << endl;
B* pb1 = (B*)ptr1;
B* pb2 = (B*)ptr2;
cout << pb1 << endl;
cout << pb2 << endl << endl;
return 0;
}
但是我们观察一下对象内部的成员
IO流
int main()
{
//2023 8 29
//输入多个值,默认都是用空格或者换行分割
int year, month, day;
cin >> year >> month >> day;
scanf("%d%d%d", &year, &month, &day);
scanf("%d %d %d", &year, &month, &day); //不需要去加空格
return 0;
}
三种写法都是可以的
处理连续型
int main()
{
int year, month, day;
scanf("%4d%2d%2d", &year, &month, &day);
string str;
cin >> str;
year = stoi(str.substr(0, 4));
month = stoi(str.substr(4, 2));
day = stoi(str.substr(6, 2));
return 0;
}
格式必须正确
类型转换
int main()
{
// 内置类型 转换成自定义类型
A aa1 = 1; // 隐式类型转换 用1构造A临时对象,再拷贝构造aa1,优化后直接1构造aa1
// 自定义类型 转换成内置类型
int i = aa1;
return 0;
}
class Date
{
friend ostream& operator << (ostream& out, const Date& d);
friend istream& operator >> (istream& in, Date& d);
public:
Date(int year = 1, int month = 1, int day = 1)
:_year(year)
, _month(month)
, _day(day)
{}
operator bool()
{
// 这里是随意写的,假设输入_year为0,则结束
if (_year == 0)
return false;
else
return true;
}
private:
int _year;
int _month;
int _day;
};
istream& operator >> (istream& in, Date& d)
{
in >> d._year >> d._month >> d._day;
return in;
}
ostream& operator << (ostream& out, const Date& d)
{
out << d._year << " " << d._month << " " << d._day;
return out;
}
C++ IO流,使用面向对象+运算符重载的方式
能更好的兼容自定义类型,流插入和流提取
int main()
{
// 自动识别类型的本质--函数重载
// 内置类型可以直接使用--因为库里面ostream类型已经实现了
int i = 1;
double j = 2.2;
cout << i << endl;
cout << j << endl;
// 自定义类型则需要我们自己重载<< 和 >>
Date d(2022, 4, 10);
cout << d;
while (d)
{
cin >> d;
cout << d;
}
return 0;
}
将test.cpp的内容打印到控制台上
int main()
{
ifstream ifs("test.cpp");
char ch = ifs.get();
while (ifs)
{
cout << ch;
ch = ifs.get();
}
return 0;
}