7

I'm moving from Java to C++ right now and I'm having some difficulties whenever a commonly used concept in Java doesn't map directly into C++. For instance, in Java I would do something like:

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;
}

Of course, in C++ the Fruit fruit; statement actually creates a fruit. Does this mean I have to have a default constructor? This seems unsafe! What if my default fruit escaped?

4

7 に答える 7

10

C ++は、果物の作成に関して、はるかに頭痛の種になります。必要に応じて、次のいずれかのオプションを選択できます。

1)スタックにFruitを作成し、コピーを返します(コピーコンストラクターが必要です)。名前が一致しない場合に備えて、デフォルトのフルーツを提供する必要があります。

Fruit GetFruit(const std::string &name)
{
   if ( name == "banana" ) return Fruit("banana");
   if ( name == "apple" )  return Fruit("apple");
   return Fruit("default");
}

2)ヒープ上にフルーツを作成し、nullポインターが返される可能性があることに注意してください。また、このフルーツをどこかで削除することを忘れないでください。また、所有者によって1回だけ削除されるように注意してください(そして、誰も保持していないことに注意してください。削除されたフルーツへのポインタ):

Fruit* GetFruit(const std::string &name)
{
   if ( name == "banana" ) return new Fruit("banana");
   if ( name == "apple" )  return new Fruit("apple");
   return NULL;
}

3)最後に、スマートポインターを使用して、考えられる多くのポインターの問題を回避します(ただし、nullポインターには注意してください)。このオプションは、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();
}
于 2010-07-20T15:44:53.640 に答える
8

Objects in Java are represented by pointers. Since this is pervasive, there is no special notation for pointers. In C++, objects can be represented by themselves or by pointers, so it's necessary to specify pointers when they occur.

The C++ version of your code is:

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;
}

This returns a pointer to Fruit. You would access members like fruit->color(), not fruit.color(). You should delete that pointer when you're through with it.

于 2010-07-20T15:37:07.670 に答える
4

The most straightforward way would be:

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?
}

... and a direct mapping would be to use a (preferably "smart") pointer:

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;
}
于 2010-07-20T15:38:02.683 に答える
1

C ++にはポインタがあり、Javaでは暗黙的です。オブジェクト(つまり、メモリ内のエンティティ)とそのアドレスには違いがあります。Javaでは、オブジェクトを明示的に作成する必要があります。

MyClass name;

そのクラスのオブジェクトの参照を作成しています。これは、名前が実際のオブジェクトアドレスを含む小さなメモリ位置を識別することを意味します。newを使用して家全体を構築すると、その小さなメモリ位置に割り当てられているアドレスのみが返されます。

C ++では、メモリの制御が向上し、オブジェクトを作成する方法が2つあります。ステートメントを使用する場合

MyClass object;

このオブジェクトはスタックに作成されます。これは、関数が戻ると、オブジェクトが破棄されることを意味します。new演算子を使用せずに、オブジェクトが自動的に作成されることに注意してください。オブジェクトでスタックの破棄を永続化する場合は、new演算子を使用する必要があります。この演算子は、新しく作成されたオブジェクトへのポインターを返します。

MyClass *objectPtr = new MyClass();

クラス名の後に配置された*は、そのオブジェクトの割り当てではなく、相対ポインター型を要求していることを意味します。

オブジェクトが不要になったときにメモリをクリーンアップする必要があることを忘れないでください。そうしないと、メモリリークが発生します。

delete objectPtr;

だから、あなたはこのようにすることができます:

MyClass *yourfunction(bool param) {
    if (param)
        return new MyClass(A);
    return new MyClass(B);
}

とにかく、ポインタはまったく安全ではないことを知っているはずです!ユーザーがポインターを制御できるようにすると、コードの誤り、慣行の誤り、およびまったく良くない多くのことが発生する可能性があります。即時の例:オブジェクトの使用後にメモリをクリーンアップするのを忘れた場合はどうなりますか?)

この場合、スマートポインターを使用する方が良いですが、今では言うことが多すぎます:)グーグルを楽しんでください!

こんにちは

于 2010-07-20T15:45:30.893 に答える
1

To map your example to C++, you should use a pointer. In C++, an object built is considered a valid object (therefore, with reference, you cannot have null).

Using Fruit* fruit = 0; ...

you can have an object defaulted to your need, or 0 defaulted if no test pass.

于 2010-07-20T15:34:46.057 に答える
0

Your fruit variable in java roughly maps to a C++ pointer. You're correct, you don't want to create the object on the stack, you just want a pointer to the new object that you're creating. So if you just change Fruit to Fruit* this will work (if you change the function return type as well). Just remember that you must later delete the pointer you returned from this function, there's no garbage collection to cleanup your news.

于 2010-07-20T15:36:38.957 に答える
0

Objects work somewhat differently in Java vs in C++. As you noted, in your code you would default create an object and then you run the risk of it being passed around later. To make the minimum amount of change to your code:

Fruit GetFruit(std::string fruitName) {
    if(fruitName != "apple" && fruitName != "banana")
    {
        fruitName = "kumquat";
    }
    return Fruit(fruitName);
}

However this code will result in the object itself (including all of its internal data) being copied in the return, as well as if its copied around in further use.

To be more Java-esque you would use a boost::shared_ptr instead. Then you're dealing with a reference counted object, just like in Java:

boost::shared_ptr<Fruit> GetFruit(std::string fruitName) {
    if(fruitName != "apple" && fruitName != "banana")
    {
        fruitName = "kumquat";
    }
    return new Fruit(fruitName);
}
于 2010-07-20T16:50:05.990 に答える