访问派生类对象的字段,C++与Java
Accessing fields of derived class object, C++ vs Java
如果在将派生类对象分配给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中的简单类型转换
从字面上比较苹果和橙子!
- 在java中解决这段代码时面临循环中的问题
- 尝试用java代码编译和运行c++代码
- 在这种情况下,java对象是否可以调用本机函数
- 在java中读取c++字节的位字段
- 为什么C++对链表中的下一个节点使用指针,而像 C# 或 Java 这样的语言只使用类 Node 的名称?
- 使用已使用 java 编码的 openssl 解码数据
- SWIG Java 在使用 -DSWIGWORDSIZE64 时将int64_t转换为 jlong
- Android Java USB for native cpp
- 在由Sublime文本3编译后在cmd上显示Java程序输出
- C++ equivalent to Java Map getOrDefault?
- C++ 中的 Java 样式枚举
- 是否有技术原因阻止 Java 中的 final C++ 像 const 一样严格?
- 加密在 Windows、C++ 和 Java 中传输中的数据
- Java从C++回调到C++回调
- 在 c++ 中模拟输入并在 JAVA 中读取它?
- 用C++包装 Java 库 (JNI)
- 使用 TreeSet Java 对反转进行计数
- 验证openssl c++中的签名,这是由JAVA DSA签名的?
- 如何通过 JNI 将 C 字符串表情符号传递给 Java
- 如何从保存在 Java 中C++的字节数组中读取数字?