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.
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.
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 immediately derived classes can use
protected members.
Inheritance access
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
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'
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
- The optional override and final specifiers may be
attached to virtual methods.
- They go the same place that const does, after the argument list.
- I don’t know why the virtual is required.
- override: This method overrides a base class method.
- You don’t need this to override a base class method.
- However, this stresses the intent to override,
so tell me if that’s not happening.
- final: Don’t let any derived class override this method.
- It’s very difficult to anticipate the needs of future classes.
- You’d better have an extremely good reason for specifying this.
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!
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!
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!
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.