我放弃了......
$ 5.2.7/2-"如果T是指针类型,则v应该是指向完成类类型的指针的右值,结果是类型为T的rvalue.如果T是引用类型,则v应为左值一个完整的类类型,结果是T引用的类型的左值."
根据以上所述,以下代码应该是格式良好的.
struct A{};
struct B : A{};
int main(){
B b;
A a, &ar1 = b;
B& rb1 = dynamic_cast<B&>(ar1); // Does not $5.2.7/2 apply here?
B& rb2 = dynamic_cast<B&>(a); // and also here?
}
Run Code Online (Sandbox Code Playgroud)
但事实并非如此.所有编译器都抱怨dynamic_cast的操作数不符合多态
$ 5.2.7/6-否则,v应该是多态类型的指针或左值(10.3).
所以我的问题是$ 5.2.7/2是什么意思?为什么$ 5.2.7/6会在这里踢?
在比较像这样的情况下的指针时,我想了解一些关于最佳实践的信息:
class Base {
};
class Derived
: public Base {
};
Derived* d = new Derived;
Base* b = dynamic_cast<Base*>(d);
// When comparing the two pointers should I cast them
// to the same type or does it not even matter?
bool theSame = b == d;
// Or, bool theSame = dynamic_cast<Derived*>(b) == d?
Run Code Online (Sandbox Code Playgroud) 我今天偶然发现了一个问题,似乎无法解决.我正在编译一个共享库,其中包含一个模板化的类(Derived<T>,其基础是Base)以及该类的一些显式实例化.我希望库用户从这个模板化的类扩展.当我尝试将出现问题dynamic_cast的用户的情况下,从Base*到Derived<T>*.
我已将问题缩小到这个MWE:
共享库包含以下文件:
Base.h
#ifndef BASE_H_
#define BASE_H_
class Base {
public:
Base();
virtual ~Base();
};
#endif /* BASE_H_ */
Run Code Online (Sandbox Code Playgroud)
Derived.h
#ifndef DERIVED_H_
#define DERIVED_H_
#include <Base.h>
template <typename T>
class Derived : public Base {
public:
Derived();
virtual ~Derived();
};
#endif /* DERIVED_H_ */
Run Code Online (Sandbox Code Playgroud)
Derived.cpp
#include <Derived.h>
template <typename T>
Derived<T>::Derived() :
Base() {
}
template <typename T>
Derived<T>::~Derived() {
}
// explicit instantiations
template class Derived<float>;
template class …Run Code Online (Sandbox Code Playgroud) 有人可以用尽可能简单的术语(或者你想要的那么简单)qobject_cast解释它是什么,它做了什么以及为什么我们需要将一个类类型转换为另一个类?
就像,我在转换int为char或QString可能使用的意义上进行类型转换QMessageBox,但为什么要投入不同的类?
我想投这个:
class Base
{
public:
virtual ~Base(){};
};
class Der : public Base {};
int main()
{
const Base* base = new Der;
Der* der = dynamic_cast<Der*>(base); // Error
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我该怎么办?我试图把:const Der* der = dynamic_cast<Der*>(base);保留const但这不起作用.
以下代码解释了问题.填写same_sub_class以检测到虚拟基类A的两个指针实际上是否是同一个具体类.
struct A {
...
}:
struct B : public A {
...
}:
struct C : public A {
...
}
bool same_sub_class(A * a1, A * a2){
// Fill this in to return true if a1 and a2 are
// of the same concrete class
}
Run Code Online (Sandbox Code Playgroud)
编辑:
当我查看我的应用程序时,我需要一些与上面略有不同的东西.我需要能够通过type_id对实例进行分组.
仅供参考.我有一个迷你符号algerbra系统,所以要进行操作,有时需要知道类类型进行排序和重新排列表达式很重要.
所以给出了一个指针向量,用于实例说明如何通过type_id对它们进行分组.我要么需要能够散列type_id,要么为每个类生成一个唯一的整数.
dynamic_casts比较慢,但它们比static_casts 更安全(当然,当与对象层次结构一起使用时).我的问题是,在我的调试代码中确保所有(动态)强制转换都是正确的之后,我有什么理由不将它们更改为static_casts吗?
我计划使用以下构造执行此操作.(顺便说一下,你能想到一个更好的名字assert_cast吗?也许debug_cast?)
#if defined(NDEBUG)
template<typename T, typename U>
T assert_cast(U other) {
return static_cast<T>(other);
}
#else
template<typename T, typename U>
T assert_cast(U other) {
return dynamic_cast<T>(other);
}
#endif
Run Code Online (Sandbox Code Playgroud)
编辑: Boost已经有了一些东西:polymorphic_downcast.感谢PlasmaHH指出这一点.
如果在我看来已经回答这个问题并且找不到答案,我会提前道歉.
注意:这是一个家庭作业,所以如果你觉得不舒服,我完全理解.
我有以下内容:
ptr.h:
template<typename T>
class Ptr {
T* address;
size_t* counter;
Ptr(T* address) : address(address), counter(new size_t(1)) { }
Ptr(const Ptr& other) : address(other.address), counter(other.counter)
{
++(*counter);
}
virtual ~Ptr() {
if (0 == --(*counter)) { delete address; delete counter; }
}
Ptr& operator=(const Ptr& right) {
if (address != right.address) {
if (0 == --(*counter)) { delete address; delete counter; }
address = right.address;
counter = right.counter;
++(*counter);
}
return *this;
}
T& operator*() const …Run Code Online (Sandbox Code Playgroud) 我在我的源代码中使用dynamic_cast来将指针转换为如下所示的东西,
Base *base = here storing the pointer;
Derived *derived = dynamic_cast<Derived*>(base);
Run Code Online (Sandbox Code Playgroud)
如果base没有类层次结构的指针,那么强制转换失败并返回NULL.在下一行中,我检查NULL.所以没有问题.
我遇到了崩溃转储,我的应用程序由于dynamic_cast抛出异常而崩溃.
我知道dynamic_cast只有在与引用类型一起使用时才会抛出.
任何想法当dynamic_cast与我在上面的源中使用的指针一起使用时会抛出异常吗?
看看这个小片段:
struct A {
virtual ~A() { }
};
struct B { };
bool fn() {
A *volatile a = new A;
return dynamic_cast<B *>(a);
}
Run Code Online (Sandbox Code Playgroud)
编译器是否允许dynamic_cast完全删除,并转换dynamic_cast为简单nullptr;?
这个问题的原因是这个答案.
笔记:
假设volatile意味着编译器不能假设任何东西a,因为它是volatile.这是一个问题的原因.
dynamic_cast可能不被允许删除的事实是程序中某处可能存在某种类型,它来源于A和B.
c++ ×10
dynamic-cast ×10
casting ×1
const ×1
inheritance ×1
performance ×1
pointers ×1
polymorphism ×1
qobject ×1
qt ×1
templates ×1
volatile ×1