访问派生类对象的字段,C++与Java

Accessing fields of derived class object, C++ vs Java

本文关键字:C++ Java 字段 派生 对象 访问      更新时间:2023-10-16

如果在将派生类对象分配给java中基类类型的变量后访问该对象的字段,我将获得预期的行为,即打印派生类的字段值。在c++中,属于基类的字段的值被打印出来。

在Java中,6按预期打印:

class Ideone
{
static class A {
static int a = 7;
}
static class B extends A {
static int b = 6;
}
public static void main (String[] args) throws java.lang.Exception
{
A a = new B();
System.out.println(((B)a).b);
}
}

在C++中,打印7:

#include <iostream>
using namespace std;
class Base {
int i = 7;
public:
Base(){
std::cout << "Constructor base" << std::endl;
}
~Base(){
std::cout << "Destructor base" << std::endl;
}
Base& operator=(const Base& a){
std::cout << "Assignment base" << std::endl;
}
};
class Derived : public Base{
public:
int j = 6;
};
int main ( int argc, char **argv ) {
Base b;
Derived p;
cout << p.j << endl;
b = p;
Derived pcasted = static_cast<Derived&>(b);
cout << pcasted.j << endl;
return 0;
}

是否可以在c++中实现类似类型的行为(打印6)。

是否可以在c++中实现类似类型的行为(打印6)。

当然是这样,只要你做的事情和在Java中做的一样。

您必须记住,尽管Java有相似的语法,但它并不完全相同。在Java中,语句A a = new B();创建一个基类型的引用,绑定到派生类型。((B)a)然后将引用的类型向下强制转换为派生类型。

在c++中,Base b;不是一个引用变量。复制将派生对象指定给该变量将复制派生对象的基本子对象。这种语言特性被称为切片。只需使用一个与Java代码具有相似语义的引用:

Base& b = p;

如果通过Derived&引用访问具体类型为Base的对象,则调用未定义的行为。

请注意,尽管返回类型为非void,但您的赋值运算符不会返回任何内容。不返回具有未定义的行为。

在C++代码中,b = p;只是将p切片复制到b,实际上b仍然是Base。则static_cast<Derived&>(b)将失败并导致UB。

您可以使用引用或指针,让b实际上指向Derived。然后可以将其向下投射到Derived

int main ( int argc, char **argv ) {
Derived p;
Base& b = p;
cout << static_cast<Derived&>(b).j << endl;
return 0;
}

实时

如果您的C++代码甚至接近于Java代码,那么您的问题可能会很有意义。事实并非如此。即使它们是用同一种语言编写的,两个不等价的代码部分会产生不同的结果也就不足为奇了。

形式的CCD_ 15

int main ( int argc, char **argv )
{
Base *b = new Derived;
std::cout << ((Derived *)p)->j << endl;
return 0;
}

(大致)相当于Java代码,考虑到Java将C++中称为指针和引用的概念混合在一起。它会给你带来你期望的结果。

将语句std::cout << ((Derived *)p)->j << endl更改为等效的(在C++中)std::cout << (*((Derived *)p)).j << endl,这可能是对Java代码的更字面的解释。

事实上,你的main()函数无论如何都会产生未定义的行为,所以所有的赌注都是无效的

Derived pcasted = static_cast<Derived&>(b);

将对CCD_ 19的引用转换为对Derived的引用。由于b不是类型Derived,所以pcasted的分配将b视为Derived,而不是。这就产生了不明确的行为。

代码差异:

  • 静态和非静态成员变量
  • 堆栈对象与堆(引用)对象
  • 堆栈对象的C++中的对象切片,以及Java中的简单类型转换

从字面上比较苹果和橙子!