标签: downcast

为什么我不能在模板参数中向下指向成员?

如果我创建一个指向基类的成员,我通常可以将它转换为指向派生的成员,但是在下面的Buzz模板中使用时,第一个模板参数会影响第二个模板参数.我是在与编译器错误斗争还是标准真的要求这不起作用?

struct Foo
{
    int x;
};

struct Bar : public Foo
{
};

template<class T, int T::* z>
struct Buzz
{
};

static int Bar::* const workaround = &Foo::x;

int main()
{
    // This works. Downcasting of pointer to members in general is fine.
    int Bar::* y = &Foo::x;

    // But this doesn't, at least in G++ 4.2 or Sun C++ 5.9. Why not?
    // Error: could not convert template argument '&Foo::x' to 'int Bar::*'
    Buzz<Bar, &Foo::x> test;

    // …
Run Code Online (Sandbox Code Playgroud)

c++ templates downcast pointer-to-member implicit-cast

5
推荐指数
1
解决办法
1037
查看次数

在使用工厂模式时,我应该以任何方式避免向下转型吗?

我正在开发一个实现专有协议的服务器项目。服务器是用C++实现的工厂模式,我们现在面临着向下转型的问题。

我正在研究的协议是为自动控制慢速网络而设计的,例如RS485、ZigBee、窄带PLC 等。我们设计了工厂模式的主服务器。当接收到新帧时,我们首先识别该帧的关联设备类型,调用工厂方法生成新的“解析器”实例,并将帧分派给解析器实例。

我们的专有协议是纯二进制实现的,我们可能需要的每一个信息都记录在帧本身中,因此可以尽可能简单地定义基本接口。我们还将为我们的工厂实现自动注册方法(此处省略了与 std::map 操作相关的详细代码):

// This is our "interface" base-class
class parser
{
public:
    virtual int parse(unsigned char *) = 0;
    virtual ~parser() { }
};

// The next two classes are used for factory pattern
class instance_generator
{
public:
    virtual parser *generate() = 0;
};

class parser_factory
{
private:
    static std::map<int,instance_generator*> classDB;
public:
    static void add(int id, instance_generator &genrator);
    parser *get_instance(int id);
};

// the two template classes are implementations of "auto-regisrtation"
template <class G, int ID> …
Run Code Online (Sandbox Code Playgroud)

c++ oop downcast factory-pattern

5
推荐指数
1
解决办法
1438
查看次数

如何强迫对仿制品进行贬低

鉴于以下代码:

class Animal
{ }

class Dog : Animal
{ }

class Cage<T>
{
    private T animal;

    public Cage(T animal)
    {
        this.animal = animal;
    }

    public T Animal
    { 
        get { return animal;} 
    }
}

class Program
{
    static void Main(string[] args)
    {
        Dog dog = new Dog();
        Cage<Animal> animalCage = new Cage<Animal>(dog);
        Cage<Dog> dogCage = (Cage<Dog>)animalCage;
    }
}
Run Code Online (Sandbox Code Playgroud)

如何解决最后一个编译器错误(从animalCage转换为dogCage)?

在我的代码中我知道笼子里有一只狗,但是我找不到一种方法来施放它.我是创建转换器并从Cage <Animal>的值创建新的Cage <Dog>实例的唯一替代方法吗?

c# generics downcast

5
推荐指数
1
解决办法
2362
查看次数

向下转型 unique_ptr 以访问函数

如何让它发挥作用?之前的错误/注释行return 0;

#include <iostream> 
#include <vector>
#include <memory>

using namespace std;


class Base 
{
    public:   
        void foobar() { cout << "foobar"; }
};

class Derived : public Base
{
    public:

        void print() { cout << "hello world!"; }
};

int main(int argc, char *argv[]) 
{
    vector<unique_ptr<Base>> bases;
    bases.push_back(unique_ptr<Base> (new Derived()));

    //ok
    bases[0]->foobar();
    //error
    //how can I make this works?
    static_cast<Derived*> (bases[0])->print();

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

c++ downcast static-cast unique-ptr

5
推荐指数
1
解决办法
1万
查看次数

如何从非多态虚拟基类转发?

当没有涉及虚函数时,有没有办法从虚拟基类转发到派生类?这里有一些代码来演示我在说什么:

struct Base1
{
  int data;
};

struct Base2
{
  char odd_size[9];
};

struct ViBase
{
  double value;
};


struct MostDerived : Base1, Base2, virtual ViBase
{
  bool ok;
};


void foo(ViBase &v)
{
  MostDerived &md = somehow_cast<MostDerived&>(v);  //but HOW?
  md.ok = true;
}


int main()
{
  MostDerived md;
  foo(md);
}
Run Code Online (Sandbox Code Playgroud)

请注意,该代码仅用于演示.我的真实场景相当复杂,涉及模板参数和从一个到另一个的转换,只知道第一个是第二个的基础; 它可以是普通或虚拟的基础,它可能有也可能没有虚函数.(参见底部的简化示例).我可以使用类型特征检测多态情况和虚拟/非虚拟基本情况,并解决除非多态虚拟基础之外的所有情况.这就是我要问的问题.

我真的想不出一种做演员的方法:

  • 隐含的转换是正确的; 这些只做了预告.

  • static_cast 明确禁止从虚拟基类进行转换:

    5.2.9/2 ...并且B既不是虚拟基类,D也不是虚基类的基类D....

  • dynamic_cast 也不能这样做,因为downcast需要一个多态类

    5.2.7/6否则,v应该是指向多态类型的指针或glvalue(10.3).

    10.3/1 ...声明或继承虚函数的称为多态类.

  • reinterpret_cast 在这里根本不适用.

如果 …

c++ virtual-inheritance downcast

5
推荐指数
1
解决办法
788
查看次数

dynamic_cast "this" 到派生类型:什么时候合法?

这是一个显然不起作用的代码,因为在构造函数中向下转换“this”是非法的:

#include <cassert>

class A {
protected:
        virtual ~A() {}
public:
        A();
};

class B : public A {
};

A::A() {
        assert(dynamic_cast<B*>(this));
}

int main(void) {
        B b;
        return 0;
}
Run Code Online (Sandbox Code Playgroud)

正如预期的那样,当用 g++ 编译时,断言失败。

然而,这是另一个有效的代码(至少在 g++ 4.7 中,我没有尝试过其他编译器):

#include <cassert>

class A {
protected:
        virtual ~A() {}
public:
        A() {}
        void f();
};

class B : public A {
public:
        B() {
                f();
        }
};

void A::f() {
        assert(dynamic_cast<B*>(this));
}

int main(void) {
        B b;
        return 0;
}
Run Code Online (Sandbox Code Playgroud)

我的问题是:第二个代码是否“合法”,即我可以期望任何编译器都能以这种方式工作吗? …

c++ inheritance dynamic-cast downcast

5
推荐指数
1
解决办法
1820
查看次数

c ++是否像奇怪的反复出现的模板模式一样保证将祖母基类降级为盛大的子类?

我想知道c ++是否保证将祖母基类降级为盛大的子类,就像奇怪的重复模板模式一样.以下代码在我的环境中运行良好.但是我不确定它是否适用于任何条件/环境.请告诉我你的了解.非常感谢你.

PS.老实说,我不确定我的方式要求堆栈溢出是好还是坏.如果您发现了坏点,请告诉我.再次感谢你.

#include <iostream>

template <typename GrandChild>
class GrandBase {
public:
    void print(void) {
        const GrandChild* grand_child = static_cast<const GrandChild*>(this);
        std::cout << "GrandChild::value = " << grand_child->grand_child_value << std::endl;
    }
};

template <typename Derived>
class BridgeClass : public GrandBase<Derived> {};

class GrandChild : public BridgeClass<GrandChild> {
public:
    GrandChild() = default;
    virtual ~GrandChild() = default;

    int grand_child_value = 17;
};

void test_down_casting_to_grand_base(void) {
    GrandChild a;
    a.print();
}

int main(int argc, char **argv) {
    test_down_casting_to_grand_base();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出是

GrandChild::value = …
Run Code Online (Sandbox Code Playgroud)

c++ downcast

5
推荐指数
1
解决办法
225
查看次数

如何使用非多态基类向下转型

在 C++ 中,没有使我的析构函数成为 virtual是否仍然可以向下转换我的非多态基类的指针/引用?

c++ dynamic-cast downcast

5
推荐指数
1
解决办法
696
查看次数

仅当字段是某个枚举变体时才为结构定义方法?

我有以下结构:

#[derive(Debug)]
pub struct Entry {
    pub index: usize,
    pub name: String,
    pub filename_offset: u64,
    pub entry_type: EntryType,
}

#[derive(Debug)]
pub enum EntryType {
    File {
        file_offset: u64,
        length: usize,
    },

    Directory {
        parent_index: usize,
        next_index: usize,
    },
}
Run Code Online (Sandbox Code Playgroud)

Entry是GameCube ROM文件系统表中的一个条目,它描述了一个文件或目录.我定义了各种方法,EntryEntry::read_filenameEntry::write_to_disk.但是,我有一些方法对常规文件和目录都没有意义.例如,Entry::iter_contents遍历目录的所有子条目.

我希望能够定义某些方法,例如Entry::iter_contents仅针对entry_type某个变体的条目.

我尝试EntryType变成一个特征并制作了一个DirectoryEntryInfoFileEntryInfo结构,两者都实现了EntryType.

可悲的是,这种方法存在一些问题.我有一个Vec<Entry>其他地方,这种变化将成为Vec<Entry<EntryType>>.使用这样的特质,我也没有办法垂头丧气Entry<EntryList>Entry<DirectoryEntryInfo>.我也尝试过做一些事情Any,因为这是我所知道的唯一一种在Rust中贬低的方式,但我只能投entry_type,而不是整个Entry本身.

最终,我想最终得到类似的东西: …

enums downcast type-safety type-parameter rust

5
推荐指数
1
解决办法
434
查看次数

下调“ Any”时出现Swift错误

以下代码几乎是Apple Documentation的精确复制品,编译时没有错误:

guard let firstItem = (rawItems! as? Array<Dictionary<String, Any>>)?.first else {
    throw AnError()
}

let identityRef = firstItem[kSecImportItemIdentity as String] 
               as! SecIdentity?   // !!!

guard let identity = identityRef else {
    throw AnError()
}
Run Code Online (Sandbox Code Playgroud)

标有的行!!!包含强制向下转换,而替换as!as显然会导致编译错误'Any?' is not convertible to 'SecIdentity?'...确实SecIdentity是一个类,Any甚至可能不是一个类。

我真正无法解释的是以下内容。如果我尝试使代码更安全,请使用此

guard let idenity = firstItem[kSecImportItemIdentity as String] as? SecIdentity
else {
    throw AnError()
}
Run Code Online (Sandbox Code Playgroud)

或这个

guard let idenityRef = firstItem[kSecImportItemIdentity as String] as? SecIdentity? …
Run Code Online (Sandbox Code Playgroud)

downcast optional-values swift

5
推荐指数
1
解决办法
226
查看次数