我使用shared_ptr基类的问题,我似乎无法在解除引用它时调用派生类的方法.我相信代码会比我更冗长:
class Base : public boost::enable_shared_from_this<Base>
{
public:
typedef boost::shared_ptr<BabelNet> pointer;
};
class Derived : public Base
{
public:
static pointer create()
{
return pointer(new Derived);
}
void anyMethod()
{
Base::pointer foo = Derived::create();
// I can't call any method of Derived with foo
// How can I manage to do this ?
// is dynamic_cast a valid answer ?
foo->derivedMethod(); // -> compilation fail
}
};
Run Code Online (Sandbox Code Playgroud) 我正在尝试为python编写自己的"marshal"代码,这样我就可以在Google App Engine上存储已编译的python代码,以动态的方式提供脚本.大家都可以验证,GAE不支持"marshal","pickle"不能序列化代码对象.
我发现我可以构造一个代码对象,types.CodeType()但它需要12个参数.
尽管我已经尝试过,但我找不到任何关于此调用的文档,我真的需要构建代码对象,以便我可以exec().我的问题是,有没有人知道这个types.CodeType()"构造函数" 的参数是什么或者是什么方式来反省它?我已经使用了这里info()定义的功能,但它只是吐出一般信息!
快速FAQ:
UPDATE
截至2011年7月7日,Google App Engine基础架构不允许实例化代码对象,因此我的论点没有实际意义.希望将来在GAE上得到修复.
python compiler-construction google-app-engine dynamic-cast introspection
这个问题的灵感来自于此处的评论.
请考虑以下代码段:
struct X {}; // no virtual members
struct Y : X {}; // may or may not have virtual members, doesn't matter
Y* func(X* x) { return dynamic_cast<Y*>(x); }
Run Code Online (Sandbox Code Playgroud)
有几个人建议他们的编译器会拒绝它的主体func.
但是,在我看来,这是否由标准定义取决于运行时的值x.从5.2.7([expr.dynamic.cast])部分:
表达式
dynamic_cast<T>(v)的结果是将表达式转换v为type 的结果T.T应该是对完整类类型的指针或引用,或者是"指向cv的 指针void".该dynamic_cast经营者不得抛弃常量性.如果
T是指针类型,则v应该是指向完成类类型的指针的prvalue,结果是类型的prvalueT.如果T是左值引用类型,则v应该是完整类类型的左值,结果是由引用的类型的左值T.如果T是右值引用类型,则v应该是具有完整类类型的表达式,并且结果是由引用的类型的xvalueT.如果类型
v是相同的T …
我正在研究一种通用的非侵入式智能指针实现.我在第4节中有些困惑.一个声明是
仅当结果类型是多态类类型的左值时,才计算作为typeid运算符的参数提供的表达式.
相关的示例代码是:
template<typename T>
void* startOfObject(T* p) {
void* q=static_cast<void*>(p);
typeid(q=dynamic_cast<void*>(p),*p); // This line
return q;
}
Run Code Online (Sandbox Code Playgroud)
AFAIU,它意味着q=dynamic_cast<void*>(p)如果结果类型是多态类类型的左值,则将对其进行评估.该结果意味着评价的结果dynamic_cast<void*>(p)(我想),所以dynamic_cast在任何情况下被应用.文章陈述(据我所知),如果p不是多态的话dynamic_cast就不会应用,但为什么呢?在应用它之前,如何知道结果是否是多态的?如果有人详细描述了如何执行完整的语句,将会很有帮助.
另一种说法是
如果p为NULL也存在问题 - typeid将抛出std :: bad cast.
我看到的问题是取消引用,如果p是NULL,而不是typeid(虽然它可能抛出bad_typeid,但这不是因为转换).dynamic_cast会返回一个NULL类型的指针void*,如果p是NULL,而且typeid应该能够推断出类型的信息.这是一个错字,还是我错过了什么?
class A{
public:
virtual ~A() {};
};
class B : public A{ };
int main(){
A&& p = B();
dynamic_cast<B&&>(std::move(p));
}
Run Code Online (Sandbox Code Playgroud)
抛出错误(g ++ 5.2.0):
error: conversion to non-const reference type 'std::remove_reference<A&>::type& {aka class A&}' from rvalue of type 'A' [-fpermissive]
Run Code Online (Sandbox Code Playgroud)
它试图转换std::move(p)为类型A&,但我无法弄清楚为什么.我会一直认为有必要投p转换为右值引用之前作为右值,但如果我删除std::move它编译罚款.从cppreference:
dynamic_cast < new_type > ( expression )与其他强制转换表达式类似,结果如下:
如果new_type是左值引用类型(表达式必须是左值),则为左值
如果new_type是右值引用类型(表达式可能是左值或右值),则为xvalue
甚至是N3337的5.2.7:
dynamic_cast<T>(v)如果T是指针类型,则v应该是指向完成类类型的指针的prvalue,结果是类型T的prvalue.如果T是左值引用类型,则v应该是完整类类型的左值,并且结果是由T 引用的类型的左值.如果T是右值引用类型,则v应该是具有完整类类型的表达式,并且结果是由T引用的类型的x值.
唯一要求我使用完整的类类型,std::move(p)不是吗?
考虑两个指针
A* a;
B* b;
Run Code Online (Sandbox Code Playgroud)
A和B都是多态类.如何检查a和b是否指向同一个对象?
更确切地说,如果存在类型D的某个对象d,则指定a和b指向同一对象,使得*a和*b都在d的类层次结构中的某处.
我建议以下解决方案:
dynamic_cast<void*>(a) == dynamic_cast<void*>(b)
Run Code Online (Sandbox Code Playgroud)
的确,根据标准,
dynamic_cast<void*>(v)
Run Code Online (Sandbox Code Playgroud)
产生"指向v.指向的最派生对象的指针(n3242.pdf:§5.2.7 - 7).如果两者的派生最多是同一个对象,则指针指向同一个对象.
从实际角度来看,我很确定它应该始终正常工作.但理论上,乍一看提议的平等似乎会产生假阳性,例如,如果b指向A的第一个成员(不是A的祖先).虽然实际上不可能为A及其成员获取相同的地址,因为A的虚拟表指针应位于此成员之前,因此该标准不强制要求虚拟表,也不对类布局说明任何内容.
所以,我的问题是:
从标准角度来看,建议的解决方案是否正确?
有关私人(受保护)继承或cv资格的任何警告吗?
有更好的解决方案吗?
[编辑]
我试图提供一些例子来说明一个相对复杂的场景.在这种情况下,动态横向铸造和静态铸造是模糊的.
// proposed impplementation:
template<typename P, typename Q>
bool test_ptrs(const P* p, const Q* q)
{
return (dynamic_cast<const void*>(p) == dynamic_cast<const void*>(q));
}
struct Root
{
virtual ~Root(){};
};
struct A: public Root // nonvirtually
{
};
struct B: public Root // nonvirtually
{
};
struct C: public A, B // nonvirtual diamond started with Root
{
Root …Run Code Online (Sandbox Code Playgroud) 让我为这个长期问题道歉.它尽可能短,但不幸的是,它不是很短.
我定义了两个接口,A和B:
class A // An interface
{
public:
virtual ~A() {}
virtual void whatever_A()=0;
};
class B // Another interface
{
public:
virtual ~B() {}
virtual void whatever_B()=0;
};
Run Code Online (Sandbox Code Playgroud)
然后,我有一个共享库"testc"构建类C的对象,同时实现A和B,然后传递指向它们的A接口的指针:
class C: public A, public B
{
public:
C();
~C();
virtual void whatever_A();
virtual void whatever_B();
};
A* create()
{
return new C();
}
Run Code Online (Sandbox Code Playgroud)
最后,我有一个第二个共享库"testd",它接受一个A*输入,并尝试将其转换为a B*,使用dynamic_cast
void process(A* a)
{
B* b = dynamic_cast<B*>(a);
if(b)
b->whatever_B();
else
printf("Failed!\n");
}
Run Code Online (Sandbox Code Playgroud)
最后,我有主要的应用程序,A*在库之间传递:
A* …Run Code Online (Sandbox Code Playgroud) Scott Meyer在他的书中Effective C++说dynamic_cast,用于执行安全转换或跨继承层次结构.也就是说,使用dynamic_cast将指针或对基类对象的引用转换为指针或对派生或兄弟基类对象的引用,以便您可以确定转换是否成功.
失败的强制转换由空指针(在转换指针时)或异常(在转换引用时)指示.
我想得到两个代码片段,显示在投射指针的情况下失败的强制转换,并且可以指示投射引用.
如果您有以下内容:
class Animal{};
class Bird : public Animal{};
class Dog : public Animal{};
class Penguin : public Bird{};
class Poodle : public Dog{};
Run Code Online (Sandbox Code Playgroud)
dynamic_cast只检查一个类是否是另一个类的派生类,或者一个类是否是另一个类的基类?所以,如果我有:
Bird* bird;
Animal* animal;
bird = dynamic_cast<Animal*>(bird);
animal = dynamic_cast<Bird*>(animal);
Run Code Online (Sandbox Code Playgroud)
bird现在指向一个Animal类,以便我可以使用bird->some_function();它将调用该函数Animal?而animal现在指向一Bird类,所以我可以做animal->some_function();,它会调用some_function();的Bird?
我一直试图弄清楚dynamic_cast我在网上找到的作品和资源是如何最有帮助的.如果有人能够提供其它功能的其他见解dynamic_cast以及某些有用的实例,我将非常感激.
我有两个A和B类,B继承自A.
如果我有一个shared_ptr<A>我知道的对象实际上是B子类型,我怎样才能执行动态转换来访问B的API(请记住我的对象是shared_ptr,而不仅仅是A?