我试图从C++中的java中学习一些面向对象的编程方面.不过我有在使用一些困难dynamic_cast,我会用instanceofJava编写的.
我有一个基类Cell和一个派生(抽象)类Obstacle.我已经像这样定义了它:Obstacle : public Cell并且Obstacle包含一个纯虚拟析构函数.现在在Cell课堂上我想实现一个方法bool Cell::isAccesible().我已经实现了如下:
bool Cell::isAccessible() {
Obstacle *obs = dynamic_cast<Obstacle*>(this);
if (obs != NULL) return false;
return true;
}
Run Code Online (Sandbox Code Playgroud)
但是我收到以下错误:
"运行时dynamic_cast的操作数必须具有多态类类型".
我想要实现这个的方式有什么问题?任何指导表示赞赏.
我的老师在我们的一个铸造示例中包含了以下几行.c是Circle继承自类的类的对象Point.在我搜索问题的答案"我可以将类的对象转换Point为类型Circle吗?" 我发现他使用的语法与我曾经使用的每个网站不同.这些网站都使用static_cast和dynamic_cast语法.他不会在测试中使用static_cast和dynamic_cast,我只是想知道他在使用什么以及它是如何运作的.
另外,如果你能回答我是否可以将基础对象转换为派生类型,我非常感谢你.
output << "the center of the circle is at " << (Point) c;
// casting `Circle` object `c` with type `(Point)`, calls the first overloaded >stream insertion operator"
Run Code Online (Sandbox Code Playgroud) class CBase { };
class CDerived: public CBase { };
CBase b;
CBase* pb;
CDerived d;
CDerived* pd;
pb = dynamic_cast<CBase*>(&d); // ok: derived-to-base
pd = dynamic_cast<CDerived*>(&b); // wrong: base-to-derived
Run Code Online (Sandbox Code Playgroud)
我知道"衍生的基础"演员是错误的.但它的内在原因是什么?内在的逻辑原因是什么?我想,如果没有更多的解释,很难记住这一点.谢谢!
我有一个水果类和一个从水果中继承的苹果.让我们说我有各种各样的水果.我可以说苹果,香蕉和其他水果.
问题:当我尝试从该数组的元素(水果的子)获取值时,它将无法编译.
class Fruit{
public:
Fruit();
}
class Apple : public Fruit{
public:
Apple();
int count; //number of apples in the store
}
int main(){
Fruit market[3];
market[0] = Apple();
int apples = market[0].count;
}
Run Code Online (Sandbox Code Playgroud)
我知道这是因为程序不知道它正在看苹果; 但如果我当然知道它是一个苹果(例如通过检查),我如何访问Apple.count?
在将C ++强制转换为派生类之后,我遇到了一些奇怪的事情。这是问题的简化:
class animal{
public:
animal(){
_name="animal";
}
virtual void makenoise(){
cout<<_name<<endl;
}
T get_name(){
return _name;
};
protected:
T _name;
};
class cat:public animal{
public:
cat(){
this->_name="cat";
}
private:
};
class dog:public animal{
public:
dog(){
this->_name = "dog";
}
};
Run Code Online (Sandbox Code Playgroud)
如果我按照以下方式进行动态投射,则可以正常工作。
vector<animal*> barnyard;
barnyard.push_back(new animal());
barnyard.push_back(new dog());
barnyard.push_back(new cat());
dog* dogptr = dynamic_cast<dog*>(barnyard[1]);
barnyard[1] = dogptr;
cout<<barnyard[1]->get_name()<<endl;
Run Code Online (Sandbox Code Playgroud)
但是可以通过以下方式进行:
for (int ii=0;ii<3;ii++) {
if (barnyard[ii]->get_name()=="cat"){
auto dogptr = dynamic_cast<dog*>(barnyard[ii]);
barnyard[ii] = dogptr;
cout<<barnyard[ii]->get_name()<<endl;
}
}
Run Code Online (Sandbox Code Playgroud)
给出细分错误。任何的想法?
我以以下简单形式提出我的问题:
class animal {
public:
animal() {
_name="animal";
}
virtual void makenoise(){
cout<<_name<<endl;
}
string get_name(){
return _name;
}
protected:
string _name;
};
class cat : public animal {
public:
cat() {
this->_name="cat";
}
};
class dog : public animal {
public:
dog() {
this->_name = "dog";
}
};
Run Code Online (Sandbox Code Playgroud)
我想将所有动物类型一起存储在单个容器中,例如:
vector<animal*> container;
barnyard.push_back(new animal());
barnyard.push_back(new dog());
barnyard.push_back(new cat());
Run Code Online (Sandbox Code Playgroud)
在代码的某个时刻,我需要将dog对象转换为cat对象。我需要进行的转换是设置一个新的dog对象,并用与cat对应的对象相同的索引号替换它。据我了解,dynamic_cast在这种情况下不起作用,并且基于将C ++强制转换为派生类的方法,因此提到这种转换不是一种好习惯。由于模型中的猫和狗具有不同的行为特性,因此我不想将它们的定义放入动物模型中。另一方面,将它们分别存储在不同向量中将很难处理。有什么建议么?
在我的代码中,我自然而然地,在没有考虑它的情况下,首先将派生结构类型转换为基础结构以调用重载函数,然后意识到它可能在某些情况下导致问题(尽管我老实说不知道是否哪个).
我的代码如下:
struct Base
{
//some variables
}
struct Derived : Base
{
//some more variables
}
bool func(const Base &base1, const Base &base2)
{
//do some stuff and return true or false
}
bool func(const Base &base, const Derived &derived)
{
if(func(base, (Base)derived))
return true;
else
//do some more stuff and return true or false
}
Run Code Online (Sandbox Code Playgroud)
代码编译,功能按预期工作.
我在SO和其他地方发现了很多关于向上和向下转换的问题,但它们都涉及使用指针而不是直接类型转换为基类.在这个链接中,人直接将类型转换为派生类而不是基类.我发现没有任何问题可以直接解决这个问题,但我可能根本就不知道该寻找什么,所以在这种情况下请指出正确的方向!
我假设(并在线阅读)类型转换涉及创建副本,因此(Base)derived不会简单地返回引用derived,而是使用第一个函数.我可能遇到任何其他缺点或问题吗?
c++ ×7
inheritance ×5
casting ×3
polymorphism ×2
class ×1
dynamic-cast ×1
overloading ×1
parent-child ×1
static-cast ×1