CS253: Software Development with C++

Spring 2023

Access

Show Lecture.Access as a slide show.

CS253 Access

Member access

public member access

struct Foo {
    auto ff() { return "🍟"; }
    int n = 43;
};

int main() {
    Foo f;
    cout << f.ff() << f.n;
}
🍟43
class Foo {
  public:
    auto za() { return "🍕"; }
    int n = 42;
};

int main() {
    Foo f;
    cout << f.za() << f.n;
}
🍕42

A public data member is rarely the right thing to do, but it can be justified for a class that’s really just a struct in fancy clothing. At that point, you may as well just make it a struct.

private member access

class Foo {
  private:
    auto za() { return "🍕"; }
    int n = 42;
};

int main() {
    Foo f;
    cout << f.za() << f.n;  // 🦡
}
c.cc:9: error: ‘auto Foo::za()’ is private within this context
c.cc:3: note: declared private here
c.cc:9: error: ‘int Foo::n’ is private within this context
c.cc:4: note: declared private here

Only Foo can use private members.

protected member access

class Foo {
  protected:
    auto za() { return "🍕"; }
    int n = 42;
};

int main() {
    Foo f;
    cout << f.za() << f.n;  // 🦡
}
c.cc:9: error: ‘auto Foo::za()’ is protected within this context
c.cc:3: note: declared protected here
c.cc:9: error: ‘int Foo::n’ is protected within this context
c.cc:4: note: declared protected here

Only Foo and its derived classes can use protected members.

Inheritance access

public inheritance

class B {
  public:    void pub() {}
  private:   void priv() {}
  protected: void prot() {}
};
class D : public B {
  public:
    D() {
        pub();
        priv();  // 🦡
        prot();
    }
};
int main() {
    D d;
    d.pub();
    d.priv();  // 🦡
    d.prot();  // 🦡
}
c.cc: In constructor ‘D::D()’:
c.cc:10: error: ‘void B::priv()’ is private within this context
c.cc:3: note: declared private here
c.cc:10: error: ‘void B::priv()’ is private within this context
c.cc:3: note: declared private here
c.cc:17: error: ‘void B::priv()’ is private within this context
c.cc:3: note: declared private here
c.cc:18: error: ‘void B::prot()’ is protected within this context
c.cc:4: note: declared protected here

private inheritance

class B {
  public:    void pub() {}
  private:   void priv() {}
  protected: void prot() {}
};
class D : private B {
  public:
    D() {
        pub();
        priv();  // 🦡
        prot();
    }
};
int main() {
    D d;
    d.pub();   // 🦡
    d.priv();  // 🦡
    d.prot();  // 🦡
}
c.cc: In constructor ‘D::D()’:
c.cc:10: error: ‘void B::priv()’ is private within this context
c.cc:3: note: declared private here
c.cc:10: error: ‘void B::priv()’ is private within this context
c.cc:3: note: declared private here
c.cc:16: error: ‘void B::pub()’ is inaccessible within this context
c.cc:2: note: declared here
c.cc:16: error: ‘B’ is not an accessible base of ‘D’
c.cc:17: error: ‘void B::priv()’ is private within this context
c.cc:3: note: declared private here
c.cc:17: error: ‘B’ is not an accessible base of ‘D’
c.cc:18: error: ‘void B::prot()’ is protected within this context
c.cc:4: note: declared protected here
c.cc:18: error: ‘B’ is not an accessible base of ‘D’

protected inheritance

class B {
  public:    void pub() {}
  private:   void priv() {}
  protected: void prot() {}
};
class D : protected B {
  public:
    D() {
        pub();
        priv();  // 🦡
        prot();
    }
};
int main() {
    D d;
    d.pub();   // 🦡
    d.priv();  // 🦡
    d.prot();  // 🦡
}
c.cc: In constructor ‘D::D()’:
c.cc:10: error: ‘void B::priv()’ is private within this context
c.cc:3: note: declared private here
c.cc:10: error: ‘void B::priv()’ is private within this context
c.cc:3: note: declared private here
c.cc:16: error: ‘void B::pub()’ is inaccessible within this context
c.cc:2: note: declared here
c.cc:16: error: ‘B’ is not an accessible base of ‘D’
c.cc:17: error: ‘void B::priv()’ is private within this context
c.cc:3: note: declared private here
c.cc:17: error: ‘B’ is not an accessible base of ‘D’
c.cc:18: error: ‘void B::prot()’ is protected within this context
c.cc:4: note: declared protected here
c.cc:18: error: ‘B’ is not an accessible base of ‘D’

Summary

public inheritance
Used for is-a relationships. The derived class gets the base class methods.
private inheritance
A sort of secret has-a relationship. The derived class gets the base class methods, but they’re private. It might be better to declare the base class as a private data member, instead.
protected inheritance
Used only by the confused, the desperate, and the wicked.

Specifiers

override

class General {
  public:
    virtual void foo() { cout << "base"; }
};

class Specific : public General {
  public:
    virtual void foo() override { cout << "derived"; }
};

Specific s;
s.foo();
derived

Specific::foo() says that it’s overriding a base class method, and so it is. Hooray!

override

class General {
  public:
    virtual void foo() { cout << "base"; }
};

class Specific : public General {
  public:
    virtual void Foo() override { cout << "derived"; }  // 🦡
};

Specific s;
s.foo();
c.cc:8: error: ‘virtual void main()::Specific::Foo()’ marked 
   ‘override’, but does not override

Specific::Foo() says that it’s overriding a base class method, but it’s not, because Foo is not foo. Thank you, override!

override

class General {
  public:
    virtual void foo() { cout << "base"; }
};

class Specific : public General {
  public:
    virtual void foo(int n) override { cout << n; }  // 🦡
};

Specific s;
s.foo();
c.cc:8: error: ‘virtual void main()::Specific::foo(int)’ marked 
   ‘override’, but does not override

Specific::Foo() says that it’s overriding a base class method, but it’s not, because foo() is not foo(int). Thank you, override!

final

class General {
  public:
    virtual void bar() final { cout << "base"; }
};

class Specific : public General {
  public:
    virtual void bar() { cout << "derived"; }  // 🦡
};

Specific s;
s.bar();
c.cc:8: error: virtual function ‘virtual void main()::Specific::bar()’ 
   overriding final function

Specific::bar() wants to override a base class method, but that’s not allowed by the final specifier.