简体   繁体   中英

Late binding for const attributes in C++ classes?

I know there is no late binding for class attributes. But i need a good pattern to do this:

#include <cstdlib>
#include <iostream>
using namespace std;

class B
{
public:
    const int i;
    B() : i(1) {}
};

class D : public B
{
public:
    const int i;
    D() : i(2) {}
};


int main()
{
    D d;
    B *ptr = &d;

    cout << ptr->i << endl;

    return 0;
}

Output is 1 , but I expected 2 . I guess, i should use a different pattern. Any suggestion?

The version of i that gets output is dependent on the compile-time type definition. You've defined two different variables, so you'll get two different results. The way to fix this is to make sure there's only one version of the variable. You can use a contructor in B to initialize the const variable.

class B
{
public:
    const int i;
    B() : i(1) {}
protected:
    B(int j) : i(j) {}
};

class D : public B
{
public:
    D() : B(2) {}
};

You'll need to use a virtual method, just like all late binding in C++.

class B
{
public:
    virtual int get_i() const { return 1; }
};

class D : public B
{
public:
    virtual int get_i() const { return 2; }
};

You're confusing the data members B::i (initialized to 1) and D::i (initialized to 2). They aren't the same, and calls through a B * will get B::i , not D::i .

In order to get polymorphic behavior, you'll need to use virtual functions. (Another approach is in Mark Ransom's answer.)

You're just adding new members to the derived class, which also happen to hide the members of the base class. That's not what you want. Instead, use a virtual function:

class B
{
  int m_i;
public:
  virtual ~B() { }
  virtual int get() const { return m_i; }
};

class D : public B
{
  int m_j;
public:
  virtual int get() const { return m_j; }
};

Usage:

D d;
B & b = d;
std::cout << b.get() << std::endl;  // correct dynamic dispatch

Virtual dispatch works on function members, but not data members.

If you desperately need the same-named variable in both classes, then you can use an accessor function to do the job:

#include <cstdlib>
#include <iostream>
using namespace std;

class B
{
    const int i;
public:
    B() : i(1) {}
    virtual int getI() { return i; }
};

class D : public B
{
    const int i;
public:
    D() : i(2) {}
    virtual int getI() { return i; }
};


int main()
{
    D d;
    B* ptr = &d;

    cout << ptr->getI() << endl;
}

// Output: 2

Live demo.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM