Thread: Two questions I couldn't answer

  1. #1
    Registered User
    Join Date
    Dec 2013
    Posts
    241

    Two questions I couldn't answer

    So a Co-worker of mine asked me a question I couldn't give a clear answer to.

    let's say I have a class A. now, in some function I get A parameter as a reference . in this function body, I inherit from A, add only member function, and static cast A to the derived class and use it this way.
    is this safe by the standard? I coudn't agree with myself. logically speaking, I didn't see any reason why it wouldn't work or be unsafe. but it's still very ugly technique.. what does the standard say about it?

    second question I had in mind:
    we always try to decrease code lines which are repeating themself.
    the duplicity between copy constructor and copy assg. operator (and move c.tor + move assg. operator) always seemed redundand and strange. there must be a better way than writing almost the same code twice.
    then I thought : why not using placement new on this?
    like this :

    Code:
    A& operator = (const A& rhs){
       new (this) A(rhs);
       return *this;
    }
    I wonder why this way has never being used before, the STL uses some variation of this snippet to copy/move objects from one container to another..

  2. #2
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    First question doesn't make sense because a function body can't inherit from anything. Only a class (or struct) can do that.

    As for the second question, the difference between operator = and a copy constructors is that in the assignment operator, the object is already constructed. It is a valid, existing object. Therefore, the operator = must tear down the current state and then copy over the other object's state, so it is not equivalent to the copy constructor and so you shouldn't treat them the same. Calling new is what I'd say is a big no-no. You already have a constructed object and creating a new object without calling its destructor is a big no-no.

    You can implement the copy constructor via the assignment operator (*this = that) if you don't need to use the initializer list, though. You can also factor out code that's common in both the copy constructor and the assignment operator.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  3. #3
    Registered User
    Join Date
    Dec 2013
    Posts
    241
    As for the second question, the difference between operator = and a copy constructors is that in the assignment operator, the object is already constructed. It is a valid, existing object. Therefore, the operator = must tear down the current state and then copy over the other object's state, so it is not equivalent to the copy constructor and so you shouldn't treat them the same.
    ok, so what if we have "destruct" function that the destructor calls but also the assg. operator before using the placement new?

    about the first, I meant something like this:

    Code:
    class A{
    protected:
      int x;
    public:  
    A(){ x= 9; }
    }
    
    void f (A& a){
     struct B : public A{
    void print () {  cout<<x; }
    };
    
    B& b = static_cast<B&>(a); //reinterpret_cast?
    b.print();
    
    }

  4. #4
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    For the second question, it's still a no. The constructor and destructor are special functions. The constructor shall only be called once. To call the constructor once more, it first needs to be destructed (e.g. call destructor). So you'd basically need:

    ~A();
    new (this) A(...);

    But again, this is not something I recommend. The destructor is special, and should only be called once the object's lifetime is about to end. It can have side effects, so avoid it.

    For the first question, it is something you must absolutely not do. The "A" you're passing in is NOT a "B", so this is undefined behavior. To upcast a base class to a derived class, I recommend you use dynamic_cast (and make sure the base class has at least one virtual function).
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  5. #5
    Registered User
    Join Date
    Dec 2013
    Posts
    241
    you convinced me on the first.

    about the second, I'm just thinking logically:
    usually , the compiler breaks down a class to C-struct + the methods that are now global and also accepts 'this' pointer.
    so
    Code:
    class Car{
      int dist;
      drive();
    };
    becomes (after processing)
    Code:
    struct Car{
    int dist;
    }
    
    drive(Car* this);
    now, B doesn't add any size to A , and anyway, B is driven from A, so you can upcast B* to A*,
    so eventually , what you get is

    Code:
    void print (B* this){
      std::cout<<((A*)this))->x;
    }
    which is not so bad, because B is in fact A. the only problem that may arise is with the static_cast (or reinterprect_cast). so we're downcasting only to up-cast later, and anyway, the memory address stays the same..

  6. #6
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    If the object you passed in was really a "B", then there would be no problem casting it back to a B. But if it was really an "A", regardless of how "B" looks like, your "A" is NOT a "B". Right? So you're fooling the compiler into thinking it's something it's not. How is that not undefined behavior? It may just happen to work, but an upgrade to the compiler may just break it.

    The fact that some compilers break down data and code into different segments is an implementation details. It's up the compiler manufacturers how they choose to implement that, so you can't rely on this working!
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  7. #7
    Registered User
    Join Date
    Dec 2013
    Posts
    241
    So it's UB. ok, I see.
    thanks.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Numbering questions that the user wants to answer.
    By KumarSingh in forum C Programming
    Replies: 7
    Last Post: 06-20-2012, 03:23 PM
  2. c questions again. Please answer.
    By malvado in forum C Programming
    Replies: 39
    Last Post: 06-08-2011, 11:02 AM
  3. Answer to these questions
    By mdennis10 in forum C++ Programming
    Replies: 3
    Last Post: 04-19-2011, 07:48 AM
  4. A couple of questions that someone might know the answer to...
    By Finchie_88 in forum A Brief History of Cprogramming.com
    Replies: 6
    Last Post: 04-15-2005, 08:26 AM
  5. Questions ab an answer...
    By JohnMayer in forum C Programming
    Replies: 8
    Last Post: 08-11-2002, 11:06 PM