tags:

views:

303

answers:

10

Say i have the following class :

class Abc {

    int id;

public:

    int getID() {   return id; }


    int setID(int id) { this->id = id; }
};

Is there any logical error in this ? I seem to be getting unexpected results (read : wrong values of id). I know this is not the way to write a getter .. but still there shudn't be any error in this code ?

Here is the class declaration :

class ClientConn {


  static int num;
  short pos;
  sockaddr_in tcpAddress;
  sockaddr_in udpAddress;
  int connFD;

 public:
  ClientConn();

  int getConnFD();

  void setConnFD(int connFD);

  void setPos(short pos);

  short const& getPos();

  void setUdpAddress(short port);

  void setTcpAddress(sockaddr_in address);

  void setUdpAddress(sockaddr_in address);

  void setTcpAddress(short port, char* serverIP);

  void setUdpAddress(short port, char * serverIP);

  sockaddr_in const& getTcpAddress() const;    

  sockaddr_in const& getUdpAddress() const;



};

the two functions had been defined as follows :

int ClientConn :: getConnFD() {
  return connFD;
}

void ClientConn :: setConnFD(int connFD) {
  this->connFD = connFD;    
}

I had set the value of connFD to 7 using the setter, and then when i was using the getter, i was getting the value 65534.

(Should i answer my question or keep editing my post ? im new)

+3  A: 

You have to initialize the int id with 0

Oops
+2  A: 

that won't/shouldn't compile. Your setter should have a 'void' return type.

psychotik
It should compile just fine. You get undefined behavior, for calling it, though.
GMan
+11  A: 

A few notes:

  • int getID() should be a const method.
  • Why does setID() have an int return type? It doesn't return a value. How does this even compile?
  • Are you sure the unexpected results are because of the getter/setter? Do you have a short test program to demonstrate the problem?

EDIT: Now that you posted your code, I would assume that something is stomping your variables. What compiler are you using? A memory breakpoint would be the fastest way to tell you what's going on. Assuming that's not an option, sprinkle your code with debug output that shows the current value of the variable and do a divide and conquer until you find out where it gets stomped.

Also, the new code you posted still doesn't demonstrate any actual usage. A simple test program would help.

EboMike
What do you mean by saying "should"? It neither should nor should not. It is nice to have it `const` but not necessary. And it is clear that unexpected result in caused by using uninitialized variable.
Vlad Lazarenko
It "should", as in "well-written could would define it as const". That way, you have the option to read the value even if you only have a const reference to Abc.
EboMike
Not everybody finds it beneficial to be anal about const.
DeadMG
@Dead: Not everyone writes very good C++.
GMan
@Gman: Some of us prefer to develop in a reasonable timeframe. The time spent ensuring const correctness through even a minor program is excessive for the negligible benefits.
DeadMG
@Dead: It takes time to write `const`? It's not hard at all. I like developing in a reasonable timeframe too, which is why I make sure my invariants hold...
GMan
The <pre> </pre> is not working properly when i am trying to post some more code into my question .. anyways i think i shud look for other errors as this is clearly not ..
AnkurVj
"The time spent putting const correctness into the code which should have been written const correct as the code was written the first time is worth it for the long-term benefits." - I fixed that for you.
Shynthriir
@AnkurVj: don't use `<pre>` for code. Indent it by 4 spaces, or select it and click the `100101` button.
jalf
@Dead with a little more experience you will learn that you don't have the time for fast code.
wilhelmtell
@DeadMG: Experience taught me that writting const-correct code in the first place (being used to it) does not take much time and it helps catching small errors at compile time (plus adds in *documenting* the code, being able to use constant references and knowing that invariants will hold...) A few times you will need to convert a previously constant method if the semantics change (change in requirements/change in design), but removing const from the code is *much much simpler and faster* than adding it. If you get used to tagging all *semantically* constant methods as such it becomes natural.
David Rodríguez - dribeas
It's also great for other programmers to know whether an object they pass into a function might end up getting modified or not.
EboMike
+6  A: 
 int setID(int id) { this->id = id; }

should be replaced by

void setID(int id) { this->id = id; }

And you should declare a constructor to initialize the value of id.

Xavier V.
+3  A: 

Make sure you initialize id in the constructor. That said, don't blindly create accessors. When you add code always consciously know there's a good reason for it.

wilhelmtell
+1  A: 
int getID() {   return id; }

This is fine, but it should be const:

int getID() const {   return id; }


int setID(int id) { this->id = id; }

This should not return a value:

void setID(int id) { this->id = id; }
PigBen
A: 

Your code looks (and works) correctly for me:

#include <iostream>

class Abc {

    int id;

public:

    int getID() {   return id; }


    int setID(int id) { this->id = id; }
};

int main ()
{
    std::cout << "Hello World\n";
    Abc abc;
    abc.setID(5);
    std::cout << "Result: " << abc.getID() << "\n";
}

The results are as expected:

me@here:~/tmp$ ./a.out 
Hello World
Result: 5
jsight
A: 

I wonder if you are getting unexpected results because you have not initialized id. When you instantiate your class, the value of id is uninitialized. C++ does not set to zero by default. Therefore, if you were to call getID() before ever calling setID(), you would get unpredictable results.

Here’s a revised version of your class that properly initializes id, marks the getter as const and removes the unnecessary return value from the setter. I also used the common convention of adding an underscore (_) to private member variables. This is just a matter of personal preference.

class Abc {
    int id_;

public:
    // default constructor that initializes 'id_' to zero
    Abc() : id_(0) {}

    int getID() const { return id_; }
    void setID(int id) { id_ = id; }
};
Nate
+1  A: 

My crystal ball (and EboMike's edit) sais:

You overwrite connFD in your void setUdpAddress(short port, char * serverIP);. You should be using sockaddr instead of sockaddr_in. Your lucky numbers are 3, 27 and 0x4f.

HTH.

Fozi
wats the difference between the two .. what kind of errors are likely ?
AnkurVj
`sockaddr` is guaranteed to be able to hold a `sockaddr_in`, plus whatever other address type you might encounter. If you call a function that expects a `sockaddr` then it might assume that it has more room than there is in a `sockaddr_in` and overwrite something that comes after it. This is very compiler dependent though.
Fozi
A: 

Inside your:

int setID(int id) { this->id = id; }

Why do you assume "id" is not also the member? You cannot. This is just as valid:

int setID(int id) { id = id; } // problem get's obvious now.

I bet you are assigning your (uninitialized) variable to the value it already has.

try this:

void setID(int newId) { this->id = newId; }

Note: I usually recommend NOT to place "this" everywhere. It should be obvious when you call a member (function or data) or a local variable (assuming you have no globals ;)

C++ rules for hiding names are pretty clear. `id` means the function argument, not `this->id`.
Ben Voigt