Thread: overloading

  1. #1
    ... arjunajay's Avatar
    Join Date
    May 2005
    Posts
    203

    Talking overloading

    Hi,
    Sorry to bother you again.
    I recently read that the operator '=' can't be overloaded in derived classess; but all others can be.
    If the info is correct, Why is it so?
    There was no explanation in the book but this sentence.
    Thanks for any help.

  2. #2
    Anti-Poster
    Join Date
    Feb 2002
    Posts
    1,401
    Eh...looks fine to me.
    Code:
    #include <iostream>
    
    using std::cout;
    using std::endl;
    
    class A
    {
    public:
    	int m_a;
    
    	A& operator=(const A& a)
    	{
    		m_a = a.m_a; //assign
    		return *this;
    	}
    };
    
    class B : public A //B derived from A
    {
    public:
    	int m_b;
    
    	B& operator=(const B& b)
    	{
    		this->A::operator=(b); //call base operator=
    		m_b = b.m_b; //assign
    		return *this;
    	}
    };
    
    int main()
    {
    	A a1, a2;
    	B b1, b2;
    	a1.m_a = 2;
    	a2 = a1;
    
    	cout << a2.m_a << endl;
    
    	b1.m_a = 3;
    	b1.m_b = 4;
    
    	b2 = b1;
    
    	cout << b2.m_a << " " << b2.m_b << endl;
     
    	return 0;
    }
    If I did your homework for you, then you might pass your class without learning how to write a program like this. Then you might graduate and get your degree without learning how to write a program like this. You might become a professional programmer without knowing how to write a program like this. Someday you might work on a project with me without knowing how to write a program like this. Then I would have to do you serious bodily harm. - Jack Klein

  3. #3
    C/C++Newbie Antigloss's Avatar
    Join Date
    May 2005
    Posts
    216
    Quote Originally Posted by arjunajay
    I recently read that the operator '=' can't be overloaded in derived classess; but all others can be.
    Could this overloaded be derived ?

  4. #4
    ... arjunajay's Avatar
    Join Date
    May 2005
    Posts
    203
    Could this overloaded be derived ?
    What do you mean?
    pianorain just used the A::=operator();
    Did you mean anything else.
    2) How come piano rain use b as an argument in the line
    this->A:perator=(b);
    A:: can't take b as a parameter.
    It should be an A object.

  5. #5
    Anti-Poster
    Join Date
    Feb 2002
    Posts
    1,401
    b is an A object. Since B is derived from A, and b is a B, then b is also an A.
    If I did your homework for you, then you might pass your class without learning how to write a program like this. Then you might graduate and get your degree without learning how to write a program like this. You might become a professional programmer without knowing how to write a program like this. Someday you might work on a project with me without knowing how to write a program like this. Then I would have to do you serious bodily harm. - Jack Klein

  6. #6
    ... arjunajay's Avatar
    Join Date
    May 2005
    Posts
    203

    Exclamation ???

    How is that possible?
    B inherits from A, implies B knows about A and how to handle it; but A don't have any kind of info on B, and moreover, if you pass a B to the A, A has to convert it into a type of A, right? Since A doesn't know any thing abt B how is this possible?
    Or is my concept wrong?; cause if it is, then I'd have to go back to square one on inheritance
    Last edited by arjunajay; 06-18-2005 at 04:39 AM. Reason: ???

  7. #7
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Operator = is not inherited.

    The reason for this is both simple and complicated. But since there seems to be a bit of confusion, let's recap.

    We'll call our base class B, and the derived class D.
    D deriving from B means that it's a more refined concept. It may have more functions, more variables, or just override something from the base.
    D also inherits everything from its base. Every function, every variable. Not all of them are accessible to D (private members of B aren't), but they're there, ready for the B subobject to use.
    This includes operators.
    For example, if it's possible to add two B objects together, there's no reason why you shouldn't add two Ds together. (Just don't expect the result to be a D as well - it's a B unless D redefines the addition operator.)

    However, assignment operators are the big exception.

    Assignment operators and constructors exist for a reason: to allow assigment of or initialization with values to a class object while maintaining the object's internal consistency.

    Let's assume that B stores data for a connection to some server. It has an assignment operator that assigns from a std::string by parsing it into parts:
    Code:
    B & operator =(const std::string &str) {
      std::string::size_type colpos = str.find(':');
      host = str.substr(0, colpos);
      port = str.substr(colpos+1);
      return *this;
    }
    So far, everything's fine.

    D derives from B, and it's used for a very special application of the connection to the server. This special application needs the server's ID very often. This ID can be retrieved by a special call to the server.
    While B is fully capable of issuing this call, it's something B doesn't understand. It's just another call to B. D however knows that this ID is used very often, and it also knows that it's always the same for the same server.
    So D is smart and retrieves the ID once, and then caches it:
    Code:
    class D : public B
    {
      std::string serverID;
    };
    serverID is initially set to "", but when D has retrieved the ID once, it stores it in serverID. On subsequent calls, if serverID is not "", D doesn't contact the server but just returns serverID.

    What would happen if B's assignment operator was inherited?
    Code:
    D specConn;
    specConn = "localhost:12034";
    std::string id = specConn.getId();
    So far everything's fine. The getId() call cached the server ID in the object.
    Code:
    specConn = "otherhost:9248";
    std::string id = specConn.getId();
    This still compiles. However, it doesn't work. B::operator =(const std::string &) assigns to host and port, but serverID stays the same - the cached ID of the old server. Every subsequent operation is corrupted, by a bug that's very, very hard to find.

    But the assignment operator is not inherited, luckily. The above code fails to compile. This is a partial security measure against such things.
    I say partial, because it's still possible to trick the system!
    Code:
    D specConn;
    B &refConn = specConn;
    refConn = "localhost:12034";
    Same bug, no compile error. The responsibility is yours.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  8. #8
    Registered User
    Join Date
    Apr 2003
    Posts
    2,663
    How is that possible?
    B inherits from A, implies B knows about A and how to handle it; but A don't have any kind of info on B, and moreover, if you pass a B to the A, A has to convert it into a type of A, right? Since A doesn't know any thing abt B how is this possible?
    Or is my concept wrong?; cause if it is, then I'd have to go back to square one on inheritance
    Have you read anything about what's called "polymorphism" yet? It works by assigning a derived class object to a base class pointer. For instance,

    Code:
    #include <iostream>
    #include <string>
    using namespace std;
    
    class Fruit
    {
    public:
    	virtual void display()
    	{
    		cout<<"Fruit class"<<endl;
    	}
    
    	void shout()
    	{
    		cout<<"Fruit: I'm not an aniiiimal!  I'm a piece of fruit!"<<endl;
    	}
    };
    
    class Apple : public Fruit
    {
    public:
    	void display()  //overrides
    	{
    		cout<<"Apple class."<<endl;
    	}
    
    	void greeting()
    	{
    		cout<<"Hi, I'm an apple.  What are you?"<<endl;
    	}
    };
    
    int main()
    {
    	Apple a;
    
    	//Apple functions:
    	a.display();
    	a.greeting();
    
    	//Apple function inherited from Fruit:
    	a.shout();
    
    	//Polymorphism:
    	Fruit* ptr = &a;
    	cout<<endl;
    	ptr->display(); //Apple version is called
    
    	return 0;
    }
    There is also a phenomenon known as object slicing:
    Code:
    int main()
    {
    	Apple a;
    
    	//Apple functions:
    	a.display();
    	a.greeting();
    
    	//Apple function inherited from Fruit:
    	a.shout();
    
    	//Polymorphism:
    	Fruit* ptr = &a;
    	cout<<endl;
    	ptr->display();
    
    	//Object slicing:
    	Fruit f = a;
    	f.display();  //Fruit version of display() is called
            f.greeting(); //error: greeting() is not a member of Fruit
    
    	return 0;
    }
    Last edited by 7stud; 06-18-2005 at 12:15 PM.

  9. #9
    ... arjunajay's Avatar
    Join Date
    May 2005
    Posts
    203

    Exclamation ???

    But the assignment operator is not inherited, luckily.
    Does this mean that one has to rewrite the asginment operator again from scratch in a derived class in order to make it work as it should?

    Have you read anything about what's called "polymorphism" yet? It works by assigning a derived class object to a base class pointer. For instance,
    Yes; but only the addres of the obj: is asgined to a pointer. which implies that no real asginment of data members occur, and that during runtime the prgram decies what to execute, which also implies that no loss of data occurs(see below). It never came to my mind as I have almost never used it.

    There is also a phenomenon known as object slicing:
    Sorry I haven't heard of it. Besides it causes deletion of data (like asgining a double to an int causing truncation of decimal places with out even rounding).

    P.S.
    My Brain HURTS (@ @)!
    Last edited by arjunajay; 06-20-2005 at 06:17 AM. Reason: tag

  10. #10
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Does this mean that one has to rewrite the asginment operator again from scratch in a derived class in order to make it work as it should?
    Depends. The standard assignment operator (the one taking the class itself) is automatically generated to first call the base version and then call it for every member of the derived class.
    However, custom assignment operators must be re-implemented. You can still explicitely call the base version, though. For example, in my case you could do:
    Code:
    class D : public B
    {
      D &operator =(const std::string &str) {
        B::operator =(str);
        serverId.clear();
        return *this;
      }
    };
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Overloading operators
    By ugmusicbiz in forum C++ Programming
    Replies: 2
    Last Post: 02-13-2009, 01:41 PM
  2. unary operator overloading and classes
    By coletek in forum C++ Programming
    Replies: 9
    Last Post: 01-10-2009, 02:14 AM
  3. overloading operator problems
    By almich in forum C++ Programming
    Replies: 2
    Last Post: 07-26-2004, 04:10 PM
  4. operator overloading
    By blue_gene in forum C++ Programming
    Replies: 6
    Last Post: 04-29-2004, 04:06 PM
  5. overloading
    By theLukerBoy in forum C++ Programming
    Replies: 6
    Last Post: 11-04-2002, 08:49 PM