对于类变量,向上铸造和向下铸造有什么区别?
例如,在下面的程序类中,Animal只包含一个方法但Dog类包含两个方法,那么我们如何将Dog变量转换为Animal变量.
如果完成了施法,那么我们如何使用Animal的变量调用Dog的另一种方法.
class Animal
{
public void callme()
{
System.out.println("In callme of Animal");
}
}
class Dog extends Animal
{
public void callme()
{
System.out.println("In callme of Dog");
}
public void callme2()
{
System.out.println("In callme2 of Dog");
}
}
public class UseAnimlas
{
public static void main (String [] args)
{
Dog d = new Dog();
Animal a = (Animal)d;
d.callme();
a.callme();
((Dog) a).callme2();
}
}
Run Code Online (Sandbox Code Playgroud) 我是C#(和OOP)的新手.当我有一些如下代码:
class Employee
{
// some code
}
class Manager : Employee
{
//some code
}
Run Code Online (Sandbox Code Playgroud)
问题1:如果我有其他代码执行此操作:
Manager mgr = new Manager();
Employee emp = (Employee)mgr;
Run Code Online (Sandbox Code Playgroud)
这Employee
是一个Manager
,但当我把它这样投射到Employee
它意味着我正在向上倾斜它?
问题2:
当我有几个Employee
类对象时,有些但不是全部都是它们Manager
,我怎么能在可能的情况下将它们转发?
我问的是一个非常简单的问题,但我对此感到困惑.
假设我有一个班级Parent
:
public class Parent {
int name;
}
Run Code Online (Sandbox Code Playgroud)
并有另一堂课Child.java
:
public class Child extends Parent{
int salary;
}
Run Code Online (Sandbox Code Playgroud)
最后是我的Main.java类
public class Main {
public static void main(String[] args)
{
Parent parent = new Child();
parent.name= "abcd";
}
}
Run Code Online (Sandbox Code Playgroud)
如果我做一个像儿童的对象
Child child = new Child():
Run Code Online (Sandbox Code Playgroud)
然后child
对象可以访问这两个name and salary
变量.
我的问题是:
Parent parent = new Child();
Run Code Online (Sandbox Code Playgroud)
只name
提供父类变量的访问权限.那么这条线的确切用途是什么?
Parent parent = new Child();
Run Code Online (Sandbox Code Playgroud)
而且当它使用动态多态时,为什么在执行此操作后无法访问子类的变量
Parent parent = new Child();
Run Code Online (Sandbox Code Playgroud) 因此,vtable
是由编译器维护的表,其中包含指向该类中的虚函数的函数指针.
和
将派生类的对象分配给祖先类的对象称为向上转换.
向上转换使用基类指针或引用处理派生类实例/对象; 对象不是"赋值给",这意味着覆盖值ala operator = invocation.
(感谢:Tony D)
现在,如何在运行时知道"哪个"类的虚函数应该被调用?
vtable中的哪个条目指的是应该在运行时调用的"特定"派生类的功能?
我可以这样做吗?
class A { ... };
class B : private A
{
const A &foo() const
{
return *((const A *)this);
}
};
Run Code Online (Sandbox Code Playgroud)
我可以从基类中私有地继承并将其强制转换为其基类的公共版本吗?如果没有虚拟方法,我可以这样做吗?
我的猜测是肯定的,但我想确保它安全/便携.
我想知道以下代码是否导致未定义的行为:
#include <cstddef>
#include <cstdio>
struct IA {
virtual ~IA() {}
int a = 0;
};
struct IB {
virtual ~IB() {}
int b = 0;
};
struct C: IA, IB {};
int main() {
C* pc = nullptr;
IB* pib = pc;
std::printf("%p %p", (void*)pc, (void*)pib);
}
Run Code Online (Sandbox Code Playgroud) 这编译:
import scala.collection._
trait Foo[A, +This <: SortedSet[A] with SortedSetLike[A,This]]
extends SortedSetLike[A, This] { this: This =>
def bar: This = (this: SortedSetLike[A,This]).empty
}
Run Code Online (Sandbox Code Playgroud)
但如果删除了upcast,则无法编译:
import scala.collection._
trait Foo[A, +This <: SortedSet[A] with SortedSetLike[A,This]]
extends SortedSetLike[A, This] { this: This =>
def bar: This = this.empty
}
Run Code Online (Sandbox Code Playgroud)
为什么?从extends
我们知道的子句Foo
是a SortedSetLike[A, This]
,所以upcast当然是有效的 - 但是这不表明编译器允许发生冲突的继承吗?
我开始使用C++ 0X/11中的智能指针,我遇到了一种奇怪的情况.我想使用shared_ptr来强制转换对象的实例.
类Extend继承自Base类,其中Base类具有虚拟析构函数以使其具有多态性(否则dynamic_pointer_cast会抱怨非多态类转换).
如果:
std::shared_ptr<Base> obj = std::make_shared<Base>();
Run Code Online (Sandbox Code Playgroud)
然后我做:
obj = std::dynamic_pointer_cast<Extend>(obj);
Run Code Online (Sandbox Code Playgroud)
编辑:谢谢你的答案.我问这个问题的真正原因是处理XML文档使用SAX解析器,但是我得到了上升/下降的信息.我想要的是:
std::shared_ptr<Extend> ex = std::dynamic_pointer_cast<Extend>(obj);
obj = ex;
Run Code Online (Sandbox Code Playgroud)
但它完全没有意义,相反我只会使用一个对象工厂.
假设我们有这个代码
class A {
public:
A() : x(1) {}
virtual ~A() {}
int x;
};
class B {
public:
B() : y(2) {}
virtual ~B() {}
void g()
{
cout << "B::" << y << endl;
}
int y;
};
class C : private A, private B {
public:
void f()
{
B* p = static_cast<B*>( this );
p->g();
}
};
int main()
{
C c;
((B*)&c)->g();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
投在主函数的C风格不能在C++强制类型转换(的角度来正确表达static_cast
,dynamic_cast
,reinterpret_cast
).但是首先允许这个的原因是什么?它不会伤害封装吗?
更新 这不是链接问题的重复,因为这个问题是关于C++中的设计决策.它没有问我能用或不能用语言做什么,它询问为什么可能做出某些决定.
对于以下类:
public class Parent {
//Parent members
}
public class ChildA : Parent {
//ChildA members
}
public class ChildB : Parent {
//ChildB members
}
Run Code Online (Sandbox Code Playgroud)
如果我将ChildA或ChildB实例转发到Parent实例,那么我无法访问其成员,但他们的成员仍然在那里,因为如果我转发并尝试再次访问其成员,我会发现他们仍然拥有他们的数据.
我认为这意味着父实例继续为Child类分配内存.
那么这是否意味着当我实例化一个父类,它为子类成员分配内存时,还是在我投射时才发生?
如果我们使用强制转换前进和后退,父母是否可以为多个孩子分配内存?