java.lang.Object x = new Foo()
的等效代码?java.lang.Object x = new Foo()
的等效代码?void* foo = new Foo();
您可以使用new运算符将任何内容分配给void指针,因为new、放置new等操作始终返回void指针。这样做的缺点很明显:丢失所指对象的类型信息。首先,C++缺乏反射或任何询问对象的手段。您需要将类型信息记在脑海中,并使用来回转换进行强制转换才能实际使用它。由于没有类型安全的方法从void指针转换,可能会发生一些有趣的事情。
如果这是函数的返回类型:
void* foo = some_function( _arg0 );
std::string
)的任何对象一起使用的可能性。union myType{
int a;
char b[4];
};
在C++中,没有直接的等价于 java.lang.Object x = new Foo()
,因为并不是所有的东西都是对象。但是根据你想要使用的方式,你可以实现相同的目标。
在C++中,最接近java.lang.Object x = new Foo()
的等价方式是使用抽象基类
(ABC
)。ABC是一个被设计为其他类的基类的类。您可以通过至少提供一个纯虚拟成员函数来创建ABC,并且您可以使用以下语法指定它:
class Object
{
public:
virtual int my_func() = 0; // The "= 0" means "pure virtual"
};
纯虚函数通常在基类中没有实现 (参见脚注*1)。无法创建抽象基类的实例:
int main()
{
Object obj; // not possible because Object is an ABC
}
为了使用 ABC,您必须创建一个它的子类并实现派生类中的每个纯虚成员函数:class Foo : public Object
{
public:
int my_func() { return 42; } // use of "virtual" is assumed here
};
现在,您可以创建一个Foo
的实例,同时获取指向基类的指针:
int main()
{
Object* my_obj = new Foo;
}
上面的代码使用智能指针等需要遵守通常的免责声明。为了清晰起见,我省略了此内容,但从现在开始我将使用 shared_ptr
。
您还可以获取到对 Foo
的 Object
引用,而无需担心slicing
问题。
int main()
{
Foo my_foo;
Object& obj_ref = my_foo; // OK
}
关于析构函数和抽象基类(ABC)的重要提示。在实现ABC时,通常需要在基类中使用虚拟析构函数(脚注*2)。如果您不在基类中实现虚拟析构函数,则当您尝试通过基类指针delete
一个对象时,会引发未定义行为,这是不好的。
class Object
{
public:
virtual int my_func() = 0;
};
class Foo : public Object
{
public:
int my_func() { return 42; }
};
int main()
{
Object* obj = new Foo;
delete obj; // Undefined Behavior: Object has no virtual destructor
}
基于我的实际经验,在实现ABC时,我发现唯一真正需要成为纯虚函数的成员函数是析构函数。我设计的ABC通常有许多虚方法不是纯虚的,然后只有一个虚析构函数。在我看来(可争议),这是设计ABC的好起点:将析构函数设为纯虚函数,在基类中保留最少量的非纯虚虚拟成员函数,并在基类中为纯虚析构函数提供实现。当按照这种方式进行设计时,你会发现你无法在实际代码中实现某些事情,这就是你要从这个设计中偏离的时候。
脚注:
*1 ) 基类可以在基类中为纯虚成员函数提供定义。但这不是常规做法,你可能这样做的原因有些超出了本文的范围。请注意,当你这样做时,标准中有一个特殊规则,规定你不能在声明中同时提供定义;它们必须分开写。例如:
class Object
{
public:
virtual int my_funky_method() = 0;
virtual bool is_this_ok() = 0 { return false; } // ERROR: Defn not allowed here
};
int Object::my_funky_method()
{
return 43;
}
*2)有关虚析构函数的规则确实存在例外情况。本文不涉及这些内容,但更好的经验法则是:“基类的析构函数应该是公共且虚拟的,或者受保护且非虚拟的”。
没有等价物,因为Java从托管堆中分配对象,而C++在非托管内存中分配它们。Java中的对象由JVM跟踪自动垃圾回收使用标记和清除,而C++需要显式释放所有内存。
运行时环境根本不同,因为类似的语法看起来相似是一个陷阱。
delete x;
显式销毁了对象,并且内存随之隐式释放。 - CB Baileynew X;
创建对象)的,并且第二个句子在C ++行为的普遍性方面过于自信。 - Steve Townsend// Test this
namespace external
{
template <class T>
struct var
{
private:
T *value;
public:
var(T *value)
{
this->value = value;
};
T operator &() {
return this-> value;
};
};
}
#define var external::var<void *>
/**
Use:
var i = 0;
cout << &i; // Output 0;
*/
your_pointer
的类型为void*
时,这样做是非法的。 - CB Bailey