引自here:
CMediaType mymt;
AM_MEDIA_TYPE pmt = (AM_MEDIA_TYPE*)&mymt;
CMediaType
对象可以投放到AM_MEDIA_TYPE
? 更新
有人可以认真回答cast subclasses to their base classes
背后的原则是什么,我可以反过来做吗?
UPDATE2
AM_MEDIA_TYPE/CMediaType
施放
GetMediaType(4, &m_mt);
HRESULT GetMediaType(int iPosition, CMediaType *pmt)
{
...
HRESULT STDMETHODCALLTYPE SetFormat(AM_MEDIA_TYPE *pmt)
{
m_mt = *pmt;
...
答案 0 :(得分:3)
在这种特殊情况下,CMediaType
直接扩展AM_MEDIA_TYPE
,因此演员阵容可以正常使用。 (你在谈论DirectShow类,是吗?)你总是可以安全地将子类转换为它们的基类,这就是为什么它可以工作。
这是一个带继承的简单类结构:
public class Animal {
public abstract String makeSound();
public void move(...) {
...
}
}
public class Lion extends Animal {
public String makeSound() {
return "GRRRRRR";
}
public void yawn() {
...
}
}
你可以像这样实例化一只狮子,然后安全地将它投射到动物身上:
Lion lion = new Lion();
Animal animal = (Animal) lion; //Perfectly legal
animal.move();
animal.makeSound();
通过扩展Animal
(或继承自Animal
,因为它也被称为),Lion
类声明它也是动物(它们具有is-a-relationship)因此,将狮子投射到动物并假设它具有Animal
类中定义的所有属性和方法是安全的。
但是,将基类转换为子类通常不起作用:
Animal animal = getAnimalFromSomeWhere();
Lion lion = (Lion) animal;
lion.yawn();
这不行,因为不是每只动物都是狮子。根据语言的不同,您将在运行时获得类型转换错误或未定义的行为。
有一个例外:如果您确定您拥有的对象属于特定子类,则无论如何都可以执行转换。因此,如果动物实际上是Lion
,那么这个工作就可以了:
Animal animal = getAnimalFromSomeWhere();
Lion lion = (Lion) animal; //works if animal is lion, fails otherwise
lion.yawn();
大多数语言在运行时提供类型检查(“这只动物是狮子吗?”),我不知道C ++会有什么样子,所以另一个Java-ish例子:
if (animal instanceof Lion) {
Lion lion = (Lion) animal; //safe
}
答案 1 :(得分:2)
当你想以统一的方式访问一组派生实例时,通常会进行向上转换(从子到基础)(例如,你正在构建一个Animal实例列表,但你有Lion,Cow和Cat的实例)。如果您只需要通过Animal界面访问实例,那就没问题了。您可以在upcasted实例上调用Animal方法。
当你得到的是一堆Animal实例时,情况恰恰相反,但你必须只对具有特定类型的子集进行操作。这被称为向下转换,我读到了一种普遍倾向于皱眉,但在某些情况下它只是起作用。您使用dynamic_cast
执行安全预测。如果对象不是您请求的实例,则返回null(如果使用指针,则会引发异常)。
在C中你没有课程。使用强制转换,您只需告诉编译器重新解释内存中字节数组的内容。我在GTK看到它做了很多。
这是C中的一个例子。重要提示:这是丑陋的C.我的C比1870卡车更生气,而且我很匆忙。这段代码中有很多注意事项。
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct a {
int an_int;
char a_string[8];
char another_string[16];
char a_third_string[16];
};
struct b {
int an_int;
char first_four[4];
char last_four[4];
};
int main() {
struct a *a_ptr=NULL;
struct b *b_ptr=NULL;
a_ptr = malloc(sizeof(struct a));
bzero(a_ptr, sizeof(struct a));
a_ptr->an_int =10;
strncpy(a_ptr->a_string,"hello", 8);
a_ptr->a_string[strlen("hello")] = 0;
strncpy(a_ptr->another_string,"hello2", 16);
a_ptr->another_string[strlen("hello2")] = 0;
strncpy(a_ptr->a_third_string,"hello3", 16);
a_ptr->a_third_string[strlen("hello3")] = 0;
b_ptr = (struct b *)a_ptr;
printf("%n\n", b_ptr->an_int);
printf("%s\n", b_ptr->last_four);
}
当你转换为struct b *时,你用a_ptr用新的“vision”覆盖你之前引用的内存区域。通过b,您无法访问another_string,也无法访问a_third_string。
答案 2 :(得分:1)
C 没有继承的概念,它没有基类和子类。 这个概念仅存在于 C ++ 和大多数其他面向对象的语言,如C#或Java。
原则很简单。如果您的课程Dog
和Cat
都来自Mammal
。
如果Dog和Cat是Mammal
的子类,那么它们总是Mammals
,因此总是可以转换为Mammal
。
另一种方式并非如此简单。如果您将Cat
投射到Mammal
,则可以稍后投射回Cat
。但是您无法将其强制转换为Dog
,因为它仍然是Cat
,尽管您可以通过强制转换将其存储到Mammal
类型的变量中。
答案 3 :(得分:1)
您要问的是两个不同的功能:向上转换和类型转换。这两者在C ++中是截然不同的,因为你不需要进行类型转换以进行向上转换。向上转换是指将后代类的实例视为基类的实例;这背后的原则是Liskov substitution principle。类型转换涉及重新解释类型或在C ++中转换类型。有typecasting in C++种不同的种类,每种都有typecasting operators {static_cast
,dynamic_cast
,reinterpret_cast
,const_cast
,C风格的广告。类型转换允许更一般的替换,并且不遵循违反它们的原则,这就是使用转换的C和C ++程序不是类型安全的原因。
答案 4 :(得分:0)
为什么
CMediaType
对象可以转换为AM_MEDIA_TYPE
?
这是一个设计决定。你不能把所有东西都扔给其他一切,你绝对是don't want to。此外,虽然您可以从base-to-derived或derived-to-base转换对象,但如果类定义了转换运算符,则可以在不相关的类之间进行转换。
我怀疑示例代码会创建一个CMediaType
对象以利用RAII。但是调用的函数不会使用CMediaType
,因此对象将转换为AM_MEDIA_TYPE
。
c中有这样的功能吗?
C中有强制转换,但系统不同。无法定义转换运算符,并且没有基类或派生类的语言概念。您可以编写接受一种类型对象并返回另一种对象的函数。您可能对GTK+ object model感兴趣,这是在C。
中实现的将子类转换为基类的原理是什么,我可以反过来做吗?
示例代码使用C样式转换。我强烈反对在C ++代码中。 static_cast
,dynamic_cast
,const_cast
和reinterpret_cast
都做了不同的事情,区分它们非常有用。
由于C中没有类型层次结构,因此没有向下转发或向上转发。
所以,回答你对C ++的问题:从派生到基类的转换总是安全的。你甚至不必写演员:
// BTW, prefer smart pointers like boost::scoped_ptr
Derived* foo = new Derived();
Base* bar = foo;
// or you could write simply "Base* bar = new Derived()"
回归不一定是安全的,所以你必须编写演员表并创建dynamic_cast
,这样你就知道演员是否真的成功了:
Base* foo = new Derived();
Derived* bar = dynamic_cast<Derived*>(foo);
if (bar == NULL) {
// foo didn't point to a Derived or something derived from Derived
return;
}
// foo DID point to a Derived or something derived from Derived, access it through bar
...
同样,C没有dynamic_cast
之类的东西,因为C没有类型层次结构。你可以使用C风格的演员表,但C风格的演员阵容无法报告“对不起,没有办法在这些对象之间施放。”您想要知道对象何时不相关,为此您需要使用dynamic_cast
。