标签: downcast

如何使用 SWIG 生成的接口在 C# 中正确向下转型?

我有一个非常庞大且成熟的 C++ 代码库,我正在尝试使用 SWIG 为其生成 C# 接口。我无法更改实际的 C++ 代码本身,但我们可以使用 SWIG 提供的任何内容来扩展/更新它。我面临一个问题,如下所示编写的 C++ 函数会导致 C# 出现问题。

A* SomeClass::next(A*)
Run Code Online (Sandbox Code Playgroud)

调用者可能会执行以下操作:

A* acurr = 0;
while( (acurr = sc->next(acurr)) != 0 ){
    if( acurr isoftype B ){
        B* b = (B*)a;
        ...do some stuff with b..
    }
    elseif( acurr isoftype C )
    ...
}
Run Code Online (Sandbox Code Playgroud)

本质上,迭代元素容器,根据元素的真实类型,执行不同的操作。遗憾的是,SWIG 为“next”函数生成的 C# 层执行了以下操作:

return new A();
Run Code Online (Sandbox Code Playgroud)

因此,C# 中的调用代码无法确定返回的对象是否实际上是派生类,它实际上似乎始终是基类(这确实有道理)。我遇到过几种解决方案:

  1. 使用%extend SWIG关键字在对象上添加方法并最终调用dynamic_cast。在我看来,这种方法的缺点是,这需要您了解继承层次结构。就我而言,它相当大,我认为这是一个维护问题。
  2. 使用 %factory 关键字提供方法和派生类型,并让 SWIG 自动生成dynamic_cast 代码。这似乎是一个比第一个更好的解决方案,但是经过更深入的研究,它仍然需要您寻找它可能返回的所有方法和所有可能的派生类型。再次,这是一个巨大的维护问题。我希望我有一个文档链接,但我找不到。我通过查看 SWIG 附带的示例代码发现了此功能。
  3. 创建一个 C# 方法来创建派生对象的实例并将 cPtr 传输到新实例。虽然我认为这很笨拙,但它确实有效。请参阅下面的示例。
    公共静态对象castTo(对象fromObj,类型toType)
    {
        对象 retval = …

c# c++ swig downcast

4
推荐指数
1
解决办法
3168
查看次数

尝试向下转换时出现终身错误

我有一个正在尝试遍历的错误链接列表。给定MyError,它是带有可选代码的错误链接列表,我的目标是遍历该链并返回第一个非None代码:

type BoxedError = Box<dyn std::error::Error + Send + Sync + 'static>;

#[derive(Debug)]
struct MyError {
    code: Option<u32>,
    source: Option<BoxedError>,
}

impl std::error::Error for MyError {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        self.source().map(|s| s as _)
    }
}

impl std::fmt::Display for MyError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        std::fmt::Display::fmt("", f)
    }
}

impl MyError {
    fn source(&self) -> Option<&(dyn std::error::Error + Send + Sync + 'static)> {
        self.source.as_ref().map(|c| c.as_ref())
    }

    fn …
Run Code Online (Sandbox Code Playgroud)

downcast rust

4
推荐指数
1
解决办法
397
查看次数

是否有任何C++工具可以检测到static_cast,dynamic_cast和reinterpret_cast的误用?

以下问题的答案描述的推荐用法static_cast,dynamic_cast以及reinterpret_cast在C++:

什么时候应该使用static_cast,dynamic_cast,const_cast和reinterpret_cast?

你知道有哪些工具可以用来检测这类演员的滥用吗?像PC-Lint或Coverity Static Analysis这样的静态分析工具会这样做吗?

提示这个问题的特殊情况是不适当地使用static_cast向下转换指针,编译器没有警告.我想用工具检测这种情况,而不是假设开发人员永远不会犯这个错误.

c++ static-analysis casting dynamic-analysis downcast

3
推荐指数
1
解决办法
1142
查看次数

这不是贬低?

如果我做

double d = 34.56;
int i = (int)d;
Run Code Online (Sandbox Code Playgroud)

我不是"沮丧"吗?

要么

这个术语只用于类和对象吗?


我很困惑,因为在这种情况下,我们从一个更大的double到另一个更小的"向下倾斜" int,但是在课堂上,我们从一个较小的base class到另一个更"低调" derived class.

在某种意义上,这两种惯例是否相反?

c++ conventions downcast

3
推荐指数
1
解决办法
452
查看次数

使用实体框架进行向下转型

我有一个项目,我在EF中定义了Employer一个派生类User.在我的过程中,我创建了一个用户而不知道它最终是否会成为雇主(或其他类型的用户),之后我需要转换它.起初我尝试过(Intellisense表示存在显式转换):

Employer e = (Employer) GetUser();
Run Code Online (Sandbox Code Playgroud)

但在运行时我得到了:

Unable to cast object of type 'System.Data.Entity.DynamicProxies.User_7B...0D' to type 'Employer'.
Run Code Online (Sandbox Code Playgroud)

所以我试着写一个转换器:

public partial class User
{
    public static explicit operator Employer(User u)
    {
Run Code Online (Sandbox Code Playgroud)

但我得到错误:

Error   21  'User.explicit operator Employer(User)': user-defined
conversions to or from a derived class are not allowed
C:\Users\..\Documents\Visual Studio 2010\Projects\..\Website\Models\EF.Custom.cs
Run Code Online (Sandbox Code Playgroud)

精细.然后我重载了构造函数,Employer如下所示:

public partial class Employer
{
    public Employer(User u)
    {
        this.Id = u.Id;
        this.Claims = u.Claims;
        // etc.
    }
}
Run Code Online (Sandbox Code Playgroud)

并认为我可以这样做:

Employer e = …
Run Code Online (Sandbox Code Playgroud)

c# entity-framework casting downcast asp.net-mvc-3

3
推荐指数
1
解决办法
2847
查看次数

将对象(不是指针)向下转换为已知的派生类型是否安全?

会有切片的危险吗?

result Compare(const Osp::Base::Object &obj1, const Osp::Base::Object &obj2, int &cmp) const {
    cmp = ((const Block)obj1).NumSuperBlocks() - ((const Block)obj2).NumSuperBlocks();
}
Run Code Online (Sandbox Code Playgroud)

哪里

class Block : Object {/*Filler*/}
Run Code Online (Sandbox Code Playgroud)

obj1obj2放心是Block对象?

我很想用:

    cmp = ((const Block*)&obj1)->NumSuperBlocks() - ((const Block*)&obj2)->NumSuperBlocks();
Run Code Online (Sandbox Code Playgroud)

但在阅读SO的对象切片标签的简要描述时,我很想使用前者.但我真的不想要任何讨厌的无声切片.

c++ downcast object-slicing

3
推荐指数
1
解决办法
6565
查看次数

使用static_cast(或reinterpret_cast)进行无效向下转换的安全性,无需添加成员即可继承

我想知道标准对以下代码的安全性的说法:

class A { int v; };
class B: public A { }; // no added data member

A a;
B& b = static_cast<B&>(a);
Run Code Online (Sandbox Code Playgroud)

显然的运行时类型aA,不是B,所以剧组是不是真的类型安全的.但是,由于没有添加任何成员而且没有任何内容是虚拟的,IMO的类的内存布局应该是相同的,这应该可行(可能写入更好reinterpret_cast以表明这种行为?).我的猜测是这是UB,但适用于任何编译器.或者这实际上定义得很好?还是比较危险?

此外,如果B有一些额外的非虚拟成员方法会有什么变化吗?再一次,直觉上我会说不,但我想知道标准对此有何看法.

c++ casting downcast static-cast reinterpret-cast

3
推荐指数
1
解决办法
611
查看次数

Swift中的铸造和向下铸造混乱?

class Media {
    var name :String = ""
    init(name:String) {
        self.name = name
    }
}

class Song:Media {}

class Movie:Media{}

let s1 = Song(name :"Fireproof")
var m1 :Media = s1 //upcasting

//var s2 :Song = m1
var s2:Song = m1 as Song //down casting

// var x1 :Movie = m1 as Movie //
Run Code Online (Sandbox Code Playgroud)
  1. 在行上var m1: Media = s1你可以设置m1等于s1因为m1's类型是超类s1

  2. 在线var s2: Song = m1 as Song,它被认为是"向下铸造",是因为m1: Media并且你"铸造"它"作为"一种 …

casting type-conversion downcast upcasting swift

3
推荐指数
1
解决办法
3373
查看次数

C#将派生的泛型类型转换为父类

在我问我的问题之前,这是我的结构:

public class Data : ScriptableObject {...}
public class ItemData : Data {...}
public class WeaponData : ItemData {...}

public abstract class Item<T> : Visual<T> where T : ItemData {...}
public class Weapon<T> : Item<T> where T : WeaponData {...}
Run Code Online (Sandbox Code Playgroud)

当我创建一个Weapon对象并将其分配给我时,我收到一个错误(无法从源类型转换为目标类型)Item<ItemData>.

Weapon<Foo> weapon = new Weapon<Foo>();
Item<ItemData> other = weapon;
Run Code Online (Sandbox Code Playgroud)

这是为什么?

c# generics downcast

3
推荐指数
1
解决办法
1564
查看次数

为什么编译器允许我将一个实现类转换为另一个实现类?

因此,我正忙于向下转换,试图找到有效的方法和无效的方法。我有三个类:基类Animal和两个派生类DogCat

private class Animal {
}

private class Dog extends Animal {
}

private class Cat extends Animal {
}
Run Code Online (Sandbox Code Playgroud)

出于明显的原因,编译器不允许以下代码:

Dog dog = s.new Dog();
Cat cat = (Cat) dog;
Run Code Online (Sandbox Code Playgroud)

这是因为我将一个派生类转换为另一派生类,这是不可能的。但是,如果我创建Animal一个接口类型和Cat一个接口类型,那么编译器会突然接受它,即使没有可能,也不会出现任何问题。

private interface Animal {

}

private class Dog implements Animal {

}

private interface Cat extends Animal {

}
Run Code Online (Sandbox Code Playgroud)

一旦运行与以前相同的代码,就会像预期的那样给我一个错误。

java inheritance downcast

3
推荐指数
1
解决办法
63
查看次数