高级对象强制类型转换
静态对象强制类型转换
还是那个例子
#include <iostream>
#include <string>
class Company
{
public:
Company(std::string theName, std::string product);
virtual void printInfo();
protected:
std::string name;
std::string product;
};
class TechCompany : public Company
{
public:
TechCompany(std::string theName, std::string product);
virtual void printInfo();
};
Company::Company(std::string theName, std::string product)
{
name = theName;
this->product = product;
}
void Company::printInfo()
{
std::cout << "这个公司的名字叫:" << name << "正在生产" << product << std::endl;
}
TechCompany::TechCompany(std::string theName, std::string product) : Company(theName, product)
{
}
void TechCompany::printInfo()
{
std::cout << name << "这家公司大量生产了" << product << "这款产品" << std::endl;
}
int main()
{
Company *company = new TechCompany("APPLE", "Iphone");
TechCompany *techCompany = company;
techCompany->printInfo();
delete company;
company = NULL;
techCompany = NULL;
return 0;
}
这里面的
Company *company = new TechCompany("APPLE", "Iphone");
TechCompany *techCompany = company;
这里理论上是没问题的,但是实际上会报错
第二行有问题,就需要用到以下操作:
Company *company = new TechCompany("APPLE", "Iphone");
TechCompany *techCompany = (TechCompany *)company;
把后面的那个指针变量转变成TechCompany *类型。
注意,现在看起来是对的,但是如果在delete company后面再写一个delete techCompany就会报错。这是因为这两个指针实际指向的是同一块地址,重复释放就会出错。
要点总结
我们用传统的强制类型转换实现:把所需要的指针类型放在一对圆括号之间,然后写出将被强制转换的地址值。
注意不能即删除company,有删除techCompany,因为强制类型转换操作不会创建一个副本拷贝,它只是告诉编译器把有关变量解释为另一种类型组合形式,所以它们指向的是同一地址。
动态对象强制类型转换
虽然刚刚那个例子看起来不错,但是它仍有一个问题没有解决:万一被强制转换的类型和目标类型结构完全不同,怎么办,上一个类型两个其实是一个类型的,是全部继承过来的。
编译器很笨的,它任然按照我们的代码行事!这样子的程序是相当危险的,随时可能崩溃以及被崩溃。
因为在类继承关系之间跳来跳去(也就是对有关对象进行强制类型转换)在面向对象的程序里非常重要,所以C++程序员准备了几个新的强制类型转换操作符。
语法 | 说明 |
---|---|
const_cast<MyClass *>(value) | 用来改变value的“常量性” |
dynamic_cast<MyClass *>(value) |
用来把一种类型的对象指针安全地强制转换为另一种类型的对象指针。 注:如果value的类型不是一个MyClass类(或MyClass的子类)的指针,这个操作符返回NULL。 |
reinterpret_cast<T>(value) | 在不进行任何实质性的转换的情况下,把一种类型的指针解释为另一种类型的指针或者把一种整数解释为另一种整数。 |
static_cast<T>(value) | 用来进行强制类型转换而不做任何运行时检查,老式强制类型转换操作的替代品。 |
注:经常用到的是第二种。另外,只要你喜欢,你仍可以在C++里继续使用C的强制转换操作符(像上面的那个),但表中的操作符还能进行必要的类型检查(可以加个if,看看输出的指针类型是不是NULL),因而能够改善程序的可靠性。
动态强制类型转换的语法与刚刚我们学到的有很大不同,它看起来更像是一个函数调用:
Company *Company = new Company("APPLE", "Iphone");
TechCompany *techCompany = dynamic_cast<TechCompany *>(company);
先在两个尖括号之间写出想要的指针类型,然后是将被转换的值写在括号中。
#include <iostream>
#include <string>
class Company
{
public:
Company(std::string theName, std::string product);
virtual void printInfo();
protected:
std::string name;
std::string product;
};
class TechCompany : public Company
{
public:
TechCompany(std::string theName, std::string product);
virtual void printInfo();
};
Company::Company(std::string theName, std::string product)
{
name = theName;
this->product = product;
}
void Company::printInfo()
{
std::cout << "这个公司的名字叫:" << name << "正在生产" << product << std::endl;
}
TechCompany::TechCompany(std::string theName, std::string product) : Company(theName, product)
{
}
void TechCompany::printInfo()
{
std::cout << name << "这家公司大量生产了" << product << "这款产品" << std::endl;
}
int main()
{
Company *company = new TechCompany("APPLE", "Iphone");
TechCompany *techCompany = dynamic_cast<TechCompany *>(company);
techCompany->printInfo();
delete company;
company = NULL;
techCompany = NULL;
return 0;
}
如果再改一下
#include <iostream>
#include <string>
class Company
{
public:
Company(std::string theName, std::string product);
virtual void printInfo();
protected:
std::string name;
std::string product;
};
class TechCompany : public Company
{
public:
TechCompany(std::string theName, std::string product);
virtual void printInfo();
};
Company::Company(std::string theName, std::string product)
{
name = theName;
this->product = product;
}
void Company::printInfo()
{
std::cout << "这个公司的名字叫:" << name << "正在生产" << product << std::endl;
}
TechCompany::TechCompany(std::string theName, std::string product) : Company(theName, product)
{
}
void TechCompany::printInfo()
{
std::cout << name << "这家公司大量生产了" << product << "这款产品" << std::endl;
}
int main()
{
Company *company = new Company("APPLE", "Iphone");//改了这里
TechCompany *techCompany = dynamic_cast<TechCompany *>(company;
techCompany->printInfo();
delete company;
company = NULL;
techCompany = NULL;
return 0;
}
就会报错,因为就像上面表格里面的第二种“如果value的类型不是一个MyClass类(或MyClass的子类)的指针,这个操作符返回NULL”,这里就是返回了一个NULL指针,所以下面的就报错,有兴趣的话可以验证一下techCompany是不是一个NULL指针。