Karmen
Karmen

Reputation: 1

Setting char* properties of a class

I have 10 char* properties of my class called Car,what is the best way to write the setters of these 10 char* properties? One way is to directly set the value in it :

void Car<T>::setKey(const char* toCopyKey)
{
   delete[] key;
   int length=strlen(toCopyKey);
   key=new char[length+1];
   strcpy(key,toCopyKey);
} 

and do this 10 times ,other solution I thought of , is to make a function that creates a copy of the passed char* and then assigns it in the setter :

char* Car<T>::copyString(const char* s)
{
    int length=strlen(s);
    char* property=new char[length+1];
    strcpy(property,s);
    return property;
}

and use the copyString method in every setter like this :

void Car<T>::setModel(const char* toCopyModel)
{ 
    delete[] model;
    model=copyString(toCopyModel);    
 }

But I was wondering if this second solution is correct and if there is a better way to do this copying?I cannot use std::string and vector.

Upvotes: 0

Views: 799

Answers (2)

Jens
Jens

Reputation: 9406

I guess this is an assignment of some C++ course or tutorial, because otherwise I would recommend to question the whole design.

In general, I would learn as early as possible to not do manual memory management at all and use C++ standard library smart pointers. This relieves you from the burden to write destructors, copy|move-assignment and copy|move constructors.

In your example, you could use std::unique_ptr<char[]> to hold the string data. This is also exception safe and prevents memory leaks. Creation of the unique_ptr<char[]> objects can be centralized in a helper method.

class Car {
private:
    std::unique_ptr<char[]> model;
    std::unique_ptr<char[]> key;

    static std::unique_ptr<char[]> copyString(char const* prop) {
         auto const len = std::strlen(prop);
         auto p = std::make_unique<char[]>(len+1);
         std::copy(prop, prop + len, p.get());
         p[len] = '\0';
         return p;
    }

public:
    void setModel(char const* newModel) {
         model = copyString(newModel);   
    }

    void setKey(char const* k) {
        key = copyString(k);
    }

    char const* getModel() const {
        return model.get();
    }
};

If you don't know them, I would recommend to read about the rule of zero.

Upvotes: 1

Barmar
Barmar

Reputation: 780994

You can combine your two methods by using a reference parameter:

static void Car<T>::setStringProp(char *&prop, const char *toCopyString) {
    delete[] prop;
    prop = new char[strlen(toCopyString)+1];
    strcpy(prop, toCopyString);
}

void Car<T>::setModel(const char *toCopyModel) {
    setStringProp(model, toCopyModel);
}

And make sure that your constructor initializes all the properties to NULL before calling the setters, because delete[] prop requires that it be an initialized pointer.

Car<T>::Car<T>(const char *model, const char *key, ...): model(nullptr), key(nullptr), ... {
    setModel(model);
    setKey(key);
    ...
}

Upvotes: 0

Related Questions