Re: class data member or member function argument?
On Feb 22, 2:21 am, Dwight Army of Champions
<dwightarmyofchampi...@hotmail.com> wrote:
When designing a class, how do you know whether to make a variable a
private data member or just an argument to the class's member
functions? If I make it a private data member, then it's imperative I
have a valuie for it at the time I create the object (put it in the
constructor). On the other hand, if I just use it as a member function
argument, then I have to be responsible for defining and initializing
the variable before the object is created, and then deleting the
variable after the object is deleted. THis leads to code like this:
// code begins here
// ... define and initialize many variables called MyVariable
MyClass* MyObject = new MyClass(this);
MyObject->DoSomething(MyVariable1, MyVariable2, /* ... */ );
MyObject->DoSomethingElse(MyVariable2, MyVariable6);
delete MyObject; MyObject = 0;
// delete many MyVariables
// code ends here
What is the best way to do this?
I agree buying a book on OO is a good idea, but can't recommend any.
Just to summarise very briefly, a class is generally used to represent
a type of "entity" in your program: something you could say "I've got
one of those". It might be an employee, a cat, a car, a line in a
file. Then, you can create your objects to represent individual
instances of these concepts. You want to put private data into the
class so that someone using the class can just say "I want one
employee record here", or "I'm going to use a list of cats", but they
don't need additional variables to record any specifics of an
individual cat, because the cat class itself wraps up all the data
about each cat.
You've got a couple mechanisms to avoid new and delete everywhere, and
having to explicitly initialise data members or local data. One is
scoping: the idea that your program is broken up into chunks of work -
namely a scope delimited with { and }, and variables can be placed
inside that scope. If they are classes, their constructor will run
and can initialise them to some default value, or you can typically
explicitly request a value. The object's destructor is then called at
the end of that scope, so you don't have to put anything in your code
to reclaim the memory. For example:
int fn()
{
std::string x = "hello";
std::cout << x << '\n';
std::list<Cat> cats;
cats.push_back("Bluey");
feed(cats);
}
fn() doesn't need any news or deletes. Similarly, in a class, you can
have data members that are STL containers and don't need explicit
initialisation.
class Cat
{
public:
Cat(const std::string& name, int age) : name_(name), age_(age)
{ }
int get_age() const { return age_; }
const std::string& name() const { return name_; }
private:
std::string name_;
int age_;
};
Again, all the memory allocation is taken care of for you. The way
the constructor is written ensures you'll have to supply a name and
age when creating an object instance, ala:
Cat cat("Smokey", 4);
Cheers,
Tony