我现在正从Java迁移到C ++,只要Java中常用的概念没有直接映射到C ++,我就会遇到一些困难。例如,在Java中我会做类似的事情:
Fruit GetFruit(String fruitName) {
Fruit fruit;
if(fruitName == "apple") fruit = new Fruit("apple");
else if(fruitName == "banana") fruit = new Fruit("banana");
else fruit = new Fruit("kumquat"); //'cause who really wants to eat a kumquat?
return fruit;
}
当然,在C ++中,Fruit fruit;
语句实际上创造了一个结果。这是否意味着我必须有一个默认的构造函数?这似乎不安全!如果我的默认水果逃脱了怎么办?
答案 0 :(得分:10)
1)在堆栈上创建一个Fruit并返回一个副本(你需要一个拷贝构造函数)然后必须提供一些默认的水果,以防名称不匹配:
Fruit GetFruit(const std::string &name)
{
if ( name == "banana" ) return Fruit("banana");
if ( name == "apple" ) return Fruit("apple");
return Fruit("default");
}
2)在堆上创建一个Fruit并注意,可能会返回空指针,并且还记得在某个地方删除这个水果,并注意它只被删除一次且仅由其所有者删除(并注意没人拿着指向已删除水果的指针):
Fruit* GetFruit(const std::string &name)
{
if ( name == "banana" ) return new Fruit("banana");
if ( name == "apple" ) return new Fruit("apple");
return NULL;
}
3)最后,使用智能指针避免许多可能的指针问题(但要处理空指针)。此选项最接近您的Java编程体验:
typedef boost::shared_ptr<Fruit> FruitRef;
FruitRef GetFruit(const std::string &name)
{
if ( name == "banana" ) return new Fruit("banana");
if ( name == "apple" ) return new Fruit("apple");
return FruitRef();
}
答案 1 :(得分:7)
Java中的对象由指针表示。由于这是普遍存在的,因此指针没有特殊的符号。在C ++中,对象可以由它们自己或通过指针表示,因此有必要在它们出现时指定它们。
您的代码的C ++版本是:
Fruit * GetFruit(std::string fruitName) {
Fruit * fruit = 0;
if (fruitname == "apple") fruit = new Fruit("apple");
else if (fruitname == "banana") fruit = new Fruit("banana");
else fruit = new Fruit("kumquat");
return fruit;
}
返回指向Fruit
的指针。您可以访问fruit->color()
之类的成员,而不是fruit.color()
。
delete
指针。
答案 2 :(得分:3)
最直接的方式是:
Fruit GetFruit(String fruitName) {
if(fruitName == "apple") return Fruit("apple");
else if(fruitName == "banana") return Fruit("banana");
else fruit = return Fruit("kumquat"); //'cause who really wants to eat a kumquat?
}
...并且直接映射将使用(最好是“智能”)指针:
auto_ptr<Fruit> GetFruit(String fruitName) {
auto_ptr<Fruit> fruit;
if(fruitName == "apple") fruit = new Fruit("apple");
else if(fruitName == "banana") fruit = new Fruit("banana");
else fruit = new Fruit("kumquat"); //'cause who really wants to eat a kumquat?
return fruit;
}
答案 3 :(得分:1)
要将示例映射到C ++,您应该使用指针。 在C ++中,构建的对象被视为有效对象(因此,通过引用,您不能为null)。
使用 水果*水果= 0; ...
你可以根据需要设置一个对象,如果没有测试通过则默认为0。
答案 4 :(得分:1)
在C ++中有一些指针,它们隐含在Java中:对象(即内存中的实体)与其地址之间存在差异。 在Java中,您需要显式创建一个对象,因为当您编写
时MyClass name;
您正在为该类的对象创建引用。这意味着name标识包含真实对象地址的小内存位置。 当您使用new构建整个房屋时,它仅返回分配给该小内存位置的地址。
在C ++中有更好的内存控制,你有两种创建对象的方法: 如果您使用声明
MyClass object;
此对象在堆栈中创建。这意味着当函数返回时,对象将被销毁。请注意,将自动创建对象,而不使用new运算符。 如果你想让一个对象持久化堆栈破坏,你应该使用new运算符,它返回一个指向新创建对象的指针:
MyClass *objectPtr = new MyClass();
放在类名后面的*表示你要求的是相对指针类型而不是该对象的分配。
请记住,当您不再需要该对象时,您必须清理内存,否则会出现内存泄漏:
delete objectPtr;
所以,你可以这样做:
MyClass *yourfunction(bool param) {
if (param)
return new MyClass(A);
return new MyClass(B);
}
无论如何,你应该知道指针根本不安全!让用户控制指针会导致错误的代码,错误的做法以及许多并不完美的事情。立即示例:如果在对象使用后忘记清理内存会怎么样?)
在这种情况下,如果你使用智能指针会更好,但现在真的太多了:)享受谷歌搜索!
HIH
答案 5 :(得分:0)
java中的fruit
变量大致映射到C ++指针。你是对的,你不想在堆栈上创建对象,你只需要一个指向你正在创建的新对象的指针。因此,如果您只需将Fruit
更改为Fruit*
,这将有效(如果您也更改了函数返回类型)。请记住,您必须稍后delete
从此函数返回的指针,没有垃圾收集来清理您的new
。
答案 6 :(得分:0)
对象在Java和C ++中的工作方式略有不同。正如您所指出的,在您的代码中,您将默认创建一个对象,然后您冒着以后传递它的风险。要对代码进行最小量的更改:
Fruit GetFruit(std::string fruitName) {
if(fruitName != "apple" && fruitName != "banana")
{
fruitName = "kumquat";
}
return Fruit(fruitName);
}
但是,此代码将导致对象本身(包括其所有内部数据)在返回中被复制,以及如果将其复制以供进一步使用。
要使用Java-esque,您可以使用boost::shared_ptr
代替。然后你正在处理一个引用计数对象,就像在Java中一样:
boost::shared_ptr<Fruit> GetFruit(std::string fruitName) {
if(fruitName != "apple" && fruitName != "banana")
{
fruitName = "kumquat";
}
return new Fruit(fruitName);
}