0

Hello,
I have some java code I want to port to C++, and first class in the Heirarchy has me stumped. I'm trying to port a simple parsing framework as an exercise to figure out how it works internally, and almost everything in the framework requires, uses, or is PubliclyClonable a class defined in java as:

public abstract class PubliclyCloneable{
    public abstract Object clone();
}

As C++ has no Object class I wanted to define the C++ version like this:

class Cloneable{
    virtual Cloneable clone()=0;
}

Visual Studio Intellisense says this isn't allowed, and I don't have a .cpp to actaully attempt to compile yet. that is the only code in my project so far. Is the proper way to do this to make a pure virtual operator=? what would be the best way to define this high level class in the heirarchy that would ensure an always deep copy of a class?

For those curious about the framework I'm trying to port it is from the book Building Parsers with Java and the source code is on its website.

2
Contributors
2
Replies
3
Views
4 Years
Discussion Span
Last Post by sciwizeh
1

Moving from Java to C++, the main thing to understand well is the distinction between Java's reference-semantics and C++'s value-semantics. Simply put, everything in Java is a reference (or placeholder, or pointer) for an object (managed by the garbage collector). In C++, everything is a value (or object, or variable) (e.g., int), which could be an address-value (pointer) (e.g., int*) or a alias for a value (reference) (e.g., int&).

Now, to the problem in your code:

class Cloneable {
  public:  // (I added 'public:', otherwise your clone() function is private).
    virtual Cloneable clone()=0;
}

There are two things to notice. First, the presence of a pure virtual function makes the class abstract, which means, in C++, that it cannot be instantiated (i.e., you cannot create an object of that class). Second, the member function clone() returns an object of type Cloneable, that is, not a reference, not a placeholder nor a pointer, but an actual object (by value). Do you see a contradiction? Such an object cannot be created because Cloneable is abstract.

Basically, to do what you want to do you have to return things by pointer:

class Cloneable{
  public:
    virtual Cloneable* clone() = 0;  // notice Cloneable* (pointer)
}

However, using a raw pointer is not really recommended for a factory function (or clone function). It is preferrable to use a smart-pointer such as std::shared_ptr or std::unique_ptr. And because std::unique_ptr is moveable into a std::shared_ptr, that is the preferred smart-pointer to use, as so:

class Cloneable{
  public:
    virtual std::unique_ptr<Cloneable> clone() = 0;
}
0

Thanks for the reply, I forgot the "public" when I was typing the question. I thought I was forgetting something simple about the C++/Java differences and it was pointers. Rookie mistake, now I feel silly. Turns out I'm more out of practice in C++ than I thought. I'll look up the smart-pointers, because I haven't used them before.

This question has already been answered. Start a new discussion instead.
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.