How to override an operator for polymorphism

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP












7















Can anyone explain to me what I'm doing wrong here?



struct X 
int x;

explicit X(int x) : x(x)

virtual X &operator++() = 0;
;

struct OK : X
int ok;

explicit OK(int ok) : X(ok), ok(ok)

X &operator++() override
ok += 10;
return *this;

;

struct MU : X
int mu;

explicit MU(int mu) : X(mu), mu(mu)

X &operator++() override
mu *= 5;
return *this;

;

int main()
X *x_base = new OK(0);
++x_base;
std::cout << x_base->x;
return 1;
;


All that I'm trying to do is to use the idea of polymorphism for operators, in special the operator++. I want to have a result something like this:





Base* base = new Derivate();



++base <--- the ++ should be called from the Derivate class






Base* base2 = ned Derivate_2();



++base <--- the ++ should be called from the Derivate_2 class





UPDATE:



The current solution to my problem is to use ++(*base) which I know about this already.



But is there any other way to do ++base instead of ++(*base)?




Thanks for the help :)










share|improve this question



















  • 2





    x_base is a pointer to X. Incrementing a pointer is not the same as applying the increment operator to the object. Your code printing x_base->x has undefined behaviour, since, after incrementing, x_base doesn't point at an object that exists. Change the incrementing to ++(*x_base).

    – Peter
    Feb 18 at 11:19











  • To your updated question the answer is no. You can not override inbuilt operators of raw pointer to Base.

    – Öö Tiib
    Feb 18 at 11:27











  • Thata's true, but you can wrap a pointer in another class and write an overload for that wrapper class.

    – john
    Feb 18 at 11:34















7















Can anyone explain to me what I'm doing wrong here?



struct X 
int x;

explicit X(int x) : x(x)

virtual X &operator++() = 0;
;

struct OK : X
int ok;

explicit OK(int ok) : X(ok), ok(ok)

X &operator++() override
ok += 10;
return *this;

;

struct MU : X
int mu;

explicit MU(int mu) : X(mu), mu(mu)

X &operator++() override
mu *= 5;
return *this;

;

int main()
X *x_base = new OK(0);
++x_base;
std::cout << x_base->x;
return 1;
;


All that I'm trying to do is to use the idea of polymorphism for operators, in special the operator++. I want to have a result something like this:





Base* base = new Derivate();



++base <--- the ++ should be called from the Derivate class






Base* base2 = ned Derivate_2();



++base <--- the ++ should be called from the Derivate_2 class





UPDATE:



The current solution to my problem is to use ++(*base) which I know about this already.



But is there any other way to do ++base instead of ++(*base)?




Thanks for the help :)










share|improve this question



















  • 2





    x_base is a pointer to X. Incrementing a pointer is not the same as applying the increment operator to the object. Your code printing x_base->x has undefined behaviour, since, after incrementing, x_base doesn't point at an object that exists. Change the incrementing to ++(*x_base).

    – Peter
    Feb 18 at 11:19











  • To your updated question the answer is no. You can not override inbuilt operators of raw pointer to Base.

    – Öö Tiib
    Feb 18 at 11:27











  • Thata's true, but you can wrap a pointer in another class and write an overload for that wrapper class.

    – john
    Feb 18 at 11:34













7












7








7








Can anyone explain to me what I'm doing wrong here?



struct X 
int x;

explicit X(int x) : x(x)

virtual X &operator++() = 0;
;

struct OK : X
int ok;

explicit OK(int ok) : X(ok), ok(ok)

X &operator++() override
ok += 10;
return *this;

;

struct MU : X
int mu;

explicit MU(int mu) : X(mu), mu(mu)

X &operator++() override
mu *= 5;
return *this;

;

int main()
X *x_base = new OK(0);
++x_base;
std::cout << x_base->x;
return 1;
;


All that I'm trying to do is to use the idea of polymorphism for operators, in special the operator++. I want to have a result something like this:





Base* base = new Derivate();



++base <--- the ++ should be called from the Derivate class






Base* base2 = ned Derivate_2();



++base <--- the ++ should be called from the Derivate_2 class





UPDATE:



The current solution to my problem is to use ++(*base) which I know about this already.



But is there any other way to do ++base instead of ++(*base)?




Thanks for the help :)










share|improve this question
















Can anyone explain to me what I'm doing wrong here?



struct X 
int x;

explicit X(int x) : x(x)

virtual X &operator++() = 0;
;

struct OK : X
int ok;

explicit OK(int ok) : X(ok), ok(ok)

X &operator++() override
ok += 10;
return *this;

;

struct MU : X
int mu;

explicit MU(int mu) : X(mu), mu(mu)

X &operator++() override
mu *= 5;
return *this;

;

int main()
X *x_base = new OK(0);
++x_base;
std::cout << x_base->x;
return 1;
;


All that I'm trying to do is to use the idea of polymorphism for operators, in special the operator++. I want to have a result something like this:





Base* base = new Derivate();



++base <--- the ++ should be called from the Derivate class






Base* base2 = ned Derivate_2();



++base <--- the ++ should be called from the Derivate_2 class





UPDATE:



The current solution to my problem is to use ++(*base) which I know about this already.



But is there any other way to do ++base instead of ++(*base)?




Thanks for the help :)







c++ polymorphism operator-overloading operators






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Feb 18 at 11:25







Vali

















asked Feb 18 at 11:14









ValiVali

1168




1168







  • 2





    x_base is a pointer to X. Incrementing a pointer is not the same as applying the increment operator to the object. Your code printing x_base->x has undefined behaviour, since, after incrementing, x_base doesn't point at an object that exists. Change the incrementing to ++(*x_base).

    – Peter
    Feb 18 at 11:19











  • To your updated question the answer is no. You can not override inbuilt operators of raw pointer to Base.

    – Öö Tiib
    Feb 18 at 11:27











  • Thata's true, but you can wrap a pointer in another class and write an overload for that wrapper class.

    – john
    Feb 18 at 11:34












  • 2





    x_base is a pointer to X. Incrementing a pointer is not the same as applying the increment operator to the object. Your code printing x_base->x has undefined behaviour, since, after incrementing, x_base doesn't point at an object that exists. Change the incrementing to ++(*x_base).

    – Peter
    Feb 18 at 11:19











  • To your updated question the answer is no. You can not override inbuilt operators of raw pointer to Base.

    – Öö Tiib
    Feb 18 at 11:27











  • Thata's true, but you can wrap a pointer in another class and write an overload for that wrapper class.

    – john
    Feb 18 at 11:34







2




2





x_base is a pointer to X. Incrementing a pointer is not the same as applying the increment operator to the object. Your code printing x_base->x has undefined behaviour, since, after incrementing, x_base doesn't point at an object that exists. Change the incrementing to ++(*x_base).

– Peter
Feb 18 at 11:19





x_base is a pointer to X. Incrementing a pointer is not the same as applying the increment operator to the object. Your code printing x_base->x has undefined behaviour, since, after incrementing, x_base doesn't point at an object that exists. Change the incrementing to ++(*x_base).

– Peter
Feb 18 at 11:19













To your updated question the answer is no. You can not override inbuilt operators of raw pointer to Base.

– Öö Tiib
Feb 18 at 11:27





To your updated question the answer is no. You can not override inbuilt operators of raw pointer to Base.

– Öö Tiib
Feb 18 at 11:27













Thata's true, but you can wrap a pointer in another class and write an overload for that wrapper class.

– john
Feb 18 at 11:34





Thata's true, but you can wrap a pointer in another class and write an overload for that wrapper class.

– john
Feb 18 at 11:34












3 Answers
3






active

oldest

votes


















9














In these two lines,



X *x_base = new OK(0);
++x_base;


you create a pointer to the new instance, and you then increment the pointer, not the pointee. The increment operator of your class hierarchy is never called, instead, this invokes the builtin increment operator for pointers. You can fix that by dereferencing the pointer first:



++*x_base; // or ++(*x_base), might be more readable


You can also work with references instead of pointers, which allows for an increment syntax without the need to derefence a pointer, e.g.



OK ok(0);
X& x_base = ok;

++x_base; // now, x_base is a reference, no need to dereference it


Note that the implementation of the operator overload that is called doesn't change the value of X::x. The std::cout << x_base->x; after the increment suggests that you expect the value to be non-zero.






share|improve this answer

























  • and in this case is any solution in order to receive the same result but instead of writing ++(*x) to write just ++x? or it's totally impossible.

    – Vali
    Feb 18 at 11:21






  • 2





    @Vali I think this answer shows that you can solve your problem by making the variable x have type X& rather than X*. Then ++x will act on the object rather than on a pointer. Frankly I think this is better than the other answer.

    – David K
    Feb 18 at 14:03



















3














To solve your second question you need to write a wrapper for your pointer class. Something like



class XPtr

public:
XPtr(X* p) : ptr(p)
X* operator->() return ptr;
X& operator*() return *ptr;
XPtr& operator++() ++*ptr; return *this;
private:
X* ptr;
;

int main()
XPtr x_base = new OK(0);
++x_base;
std::cout << x_base->x;
return 1;
;





share|improve this answer


















  • 2





    This has the very unpleasant effect of making something that acts like a pointer except when you apply ++ to it. It seems to me this violates the principle of least surprise.

    – David K
    Feb 18 at 14:08


















0














Don't do it.



First, using ++ to mean either += 10 or *= 5 should probably get you fired.



Arithmetic operators are for things that actually behave like mathematical objects or pointers/iterators. In that sense, there is almost no reason for any such object to exhibit any runtime polymorphism.



After you get ++ to work as you wish on the pointer, you better not ever iterate over any arrays of struct MU or struct OK.



Runtime polymorphism is a tool of last resort. Don't bother with it unless you actually need it.



The best solution is to get rid of the virtual and the inheritance hierarchy and the overriding. Failing that, you should just name the functions instead of using operators.



This is not a good idea.






share|improve this answer






















    Your Answer






    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













    draft saved

    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54746008%2fhow-to-override-an-operator-for-polymorphism%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    3 Answers
    3






    active

    oldest

    votes








    3 Answers
    3






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    9














    In these two lines,



    X *x_base = new OK(0);
    ++x_base;


    you create a pointer to the new instance, and you then increment the pointer, not the pointee. The increment operator of your class hierarchy is never called, instead, this invokes the builtin increment operator for pointers. You can fix that by dereferencing the pointer first:



    ++*x_base; // or ++(*x_base), might be more readable


    You can also work with references instead of pointers, which allows for an increment syntax without the need to derefence a pointer, e.g.



    OK ok(0);
    X& x_base = ok;

    ++x_base; // now, x_base is a reference, no need to dereference it


    Note that the implementation of the operator overload that is called doesn't change the value of X::x. The std::cout << x_base->x; after the increment suggests that you expect the value to be non-zero.






    share|improve this answer

























    • and in this case is any solution in order to receive the same result but instead of writing ++(*x) to write just ++x? or it's totally impossible.

      – Vali
      Feb 18 at 11:21






    • 2





      @Vali I think this answer shows that you can solve your problem by making the variable x have type X& rather than X*. Then ++x will act on the object rather than on a pointer. Frankly I think this is better than the other answer.

      – David K
      Feb 18 at 14:03
















    9














    In these two lines,



    X *x_base = new OK(0);
    ++x_base;


    you create a pointer to the new instance, and you then increment the pointer, not the pointee. The increment operator of your class hierarchy is never called, instead, this invokes the builtin increment operator for pointers. You can fix that by dereferencing the pointer first:



    ++*x_base; // or ++(*x_base), might be more readable


    You can also work with references instead of pointers, which allows for an increment syntax without the need to derefence a pointer, e.g.



    OK ok(0);
    X& x_base = ok;

    ++x_base; // now, x_base is a reference, no need to dereference it


    Note that the implementation of the operator overload that is called doesn't change the value of X::x. The std::cout << x_base->x; after the increment suggests that you expect the value to be non-zero.






    share|improve this answer

























    • and in this case is any solution in order to receive the same result but instead of writing ++(*x) to write just ++x? or it's totally impossible.

      – Vali
      Feb 18 at 11:21






    • 2





      @Vali I think this answer shows that you can solve your problem by making the variable x have type X& rather than X*. Then ++x will act on the object rather than on a pointer. Frankly I think this is better than the other answer.

      – David K
      Feb 18 at 14:03














    9












    9








    9







    In these two lines,



    X *x_base = new OK(0);
    ++x_base;


    you create a pointer to the new instance, and you then increment the pointer, not the pointee. The increment operator of your class hierarchy is never called, instead, this invokes the builtin increment operator for pointers. You can fix that by dereferencing the pointer first:



    ++*x_base; // or ++(*x_base), might be more readable


    You can also work with references instead of pointers, which allows for an increment syntax without the need to derefence a pointer, e.g.



    OK ok(0);
    X& x_base = ok;

    ++x_base; // now, x_base is a reference, no need to dereference it


    Note that the implementation of the operator overload that is called doesn't change the value of X::x. The std::cout << x_base->x; after the increment suggests that you expect the value to be non-zero.






    share|improve this answer















    In these two lines,



    X *x_base = new OK(0);
    ++x_base;


    you create a pointer to the new instance, and you then increment the pointer, not the pointee. The increment operator of your class hierarchy is never called, instead, this invokes the builtin increment operator for pointers. You can fix that by dereferencing the pointer first:



    ++*x_base; // or ++(*x_base), might be more readable


    You can also work with references instead of pointers, which allows for an increment syntax without the need to derefence a pointer, e.g.



    OK ok(0);
    X& x_base = ok;

    ++x_base; // now, x_base is a reference, no need to dereference it


    Note that the implementation of the operator overload that is called doesn't change the value of X::x. The std::cout << x_base->x; after the increment suggests that you expect the value to be non-zero.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Feb 18 at 11:27

























    answered Feb 18 at 11:19









    lubgrlubgr

    13.5k31850




    13.5k31850












    • and in this case is any solution in order to receive the same result but instead of writing ++(*x) to write just ++x? or it's totally impossible.

      – Vali
      Feb 18 at 11:21






    • 2





      @Vali I think this answer shows that you can solve your problem by making the variable x have type X& rather than X*. Then ++x will act on the object rather than on a pointer. Frankly I think this is better than the other answer.

      – David K
      Feb 18 at 14:03


















    • and in this case is any solution in order to receive the same result but instead of writing ++(*x) to write just ++x? or it's totally impossible.

      – Vali
      Feb 18 at 11:21






    • 2





      @Vali I think this answer shows that you can solve your problem by making the variable x have type X& rather than X*. Then ++x will act on the object rather than on a pointer. Frankly I think this is better than the other answer.

      – David K
      Feb 18 at 14:03

















    and in this case is any solution in order to receive the same result but instead of writing ++(*x) to write just ++x? or it's totally impossible.

    – Vali
    Feb 18 at 11:21





    and in this case is any solution in order to receive the same result but instead of writing ++(*x) to write just ++x? or it's totally impossible.

    – Vali
    Feb 18 at 11:21




    2




    2





    @Vali I think this answer shows that you can solve your problem by making the variable x have type X& rather than X*. Then ++x will act on the object rather than on a pointer. Frankly I think this is better than the other answer.

    – David K
    Feb 18 at 14:03






    @Vali I think this answer shows that you can solve your problem by making the variable x have type X& rather than X*. Then ++x will act on the object rather than on a pointer. Frankly I think this is better than the other answer.

    – David K
    Feb 18 at 14:03














    3














    To solve your second question you need to write a wrapper for your pointer class. Something like



    class XPtr

    public:
    XPtr(X* p) : ptr(p)
    X* operator->() return ptr;
    X& operator*() return *ptr;
    XPtr& operator++() ++*ptr; return *this;
    private:
    X* ptr;
    ;

    int main()
    XPtr x_base = new OK(0);
    ++x_base;
    std::cout << x_base->x;
    return 1;
    ;





    share|improve this answer


















    • 2





      This has the very unpleasant effect of making something that acts like a pointer except when you apply ++ to it. It seems to me this violates the principle of least surprise.

      – David K
      Feb 18 at 14:08















    3














    To solve your second question you need to write a wrapper for your pointer class. Something like



    class XPtr

    public:
    XPtr(X* p) : ptr(p)
    X* operator->() return ptr;
    X& operator*() return *ptr;
    XPtr& operator++() ++*ptr; return *this;
    private:
    X* ptr;
    ;

    int main()
    XPtr x_base = new OK(0);
    ++x_base;
    std::cout << x_base->x;
    return 1;
    ;





    share|improve this answer


















    • 2





      This has the very unpleasant effect of making something that acts like a pointer except when you apply ++ to it. It seems to me this violates the principle of least surprise.

      – David K
      Feb 18 at 14:08













    3












    3








    3







    To solve your second question you need to write a wrapper for your pointer class. Something like



    class XPtr

    public:
    XPtr(X* p) : ptr(p)
    X* operator->() return ptr;
    X& operator*() return *ptr;
    XPtr& operator++() ++*ptr; return *this;
    private:
    X* ptr;
    ;

    int main()
    XPtr x_base = new OK(0);
    ++x_base;
    std::cout << x_base->x;
    return 1;
    ;





    share|improve this answer













    To solve your second question you need to write a wrapper for your pointer class. Something like



    class XPtr

    public:
    XPtr(X* p) : ptr(p)
    X* operator->() return ptr;
    X& operator*() return *ptr;
    XPtr& operator++() ++*ptr; return *this;
    private:
    X* ptr;
    ;

    int main()
    XPtr x_base = new OK(0);
    ++x_base;
    std::cout << x_base->x;
    return 1;
    ;






    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Feb 18 at 11:41









    johnjohn

    37.9k12848




    37.9k12848







    • 2





      This has the very unpleasant effect of making something that acts like a pointer except when you apply ++ to it. It seems to me this violates the principle of least surprise.

      – David K
      Feb 18 at 14:08












    • 2





      This has the very unpleasant effect of making something that acts like a pointer except when you apply ++ to it. It seems to me this violates the principle of least surprise.

      – David K
      Feb 18 at 14:08







    2




    2





    This has the very unpleasant effect of making something that acts like a pointer except when you apply ++ to it. It seems to me this violates the principle of least surprise.

    – David K
    Feb 18 at 14:08





    This has the very unpleasant effect of making something that acts like a pointer except when you apply ++ to it. It seems to me this violates the principle of least surprise.

    – David K
    Feb 18 at 14:08











    0














    Don't do it.



    First, using ++ to mean either += 10 or *= 5 should probably get you fired.



    Arithmetic operators are for things that actually behave like mathematical objects or pointers/iterators. In that sense, there is almost no reason for any such object to exhibit any runtime polymorphism.



    After you get ++ to work as you wish on the pointer, you better not ever iterate over any arrays of struct MU or struct OK.



    Runtime polymorphism is a tool of last resort. Don't bother with it unless you actually need it.



    The best solution is to get rid of the virtual and the inheritance hierarchy and the overriding. Failing that, you should just name the functions instead of using operators.



    This is not a good idea.






    share|improve this answer



























      0














      Don't do it.



      First, using ++ to mean either += 10 or *= 5 should probably get you fired.



      Arithmetic operators are for things that actually behave like mathematical objects or pointers/iterators. In that sense, there is almost no reason for any such object to exhibit any runtime polymorphism.



      After you get ++ to work as you wish on the pointer, you better not ever iterate over any arrays of struct MU or struct OK.



      Runtime polymorphism is a tool of last resort. Don't bother with it unless you actually need it.



      The best solution is to get rid of the virtual and the inheritance hierarchy and the overriding. Failing that, you should just name the functions instead of using operators.



      This is not a good idea.






      share|improve this answer

























        0












        0








        0







        Don't do it.



        First, using ++ to mean either += 10 or *= 5 should probably get you fired.



        Arithmetic operators are for things that actually behave like mathematical objects or pointers/iterators. In that sense, there is almost no reason for any such object to exhibit any runtime polymorphism.



        After you get ++ to work as you wish on the pointer, you better not ever iterate over any arrays of struct MU or struct OK.



        Runtime polymorphism is a tool of last resort. Don't bother with it unless you actually need it.



        The best solution is to get rid of the virtual and the inheritance hierarchy and the overriding. Failing that, you should just name the functions instead of using operators.



        This is not a good idea.






        share|improve this answer













        Don't do it.



        First, using ++ to mean either += 10 or *= 5 should probably get you fired.



        Arithmetic operators are for things that actually behave like mathematical objects or pointers/iterators. In that sense, there is almost no reason for any such object to exhibit any runtime polymorphism.



        After you get ++ to work as you wish on the pointer, you better not ever iterate over any arrays of struct MU or struct OK.



        Runtime polymorphism is a tool of last resort. Don't bother with it unless you actually need it.



        The best solution is to get rid of the virtual and the inheritance hierarchy and the overriding. Failing that, you should just name the functions instead of using operators.



        This is not a good idea.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Feb 21 at 3:53









        KevinZKevinZ

        1,1971118




        1,1971118



























            draft saved

            draft discarded
















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54746008%2fhow-to-override-an-operator-for-polymorphism%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown






            Popular posts from this blog

            How to check contact read email or not when send email to Individual?

            Displaying single band from multi-band raster using QGIS

            How many registers does an x86_64 CPU actually have?