Modify Your Base Class Interface in Derived Classes

Modify Your Base Class Interface in Derived Classes

base class provides an interface that is inherited by derived classes. However, in some cases you need to extend, or even alter, the base class’s interface in a derived class. For example, if you’re overloading a member function of the base class in a derived class or readjusting a member’s access.

How do you overload a member function across a class hierarchy? How do you override the access type of a base class’s member in a derived class?

Use a using-declaration to control a member’s access type and to overload member functions across a class hierarchy.

Demonstrating the Problem
Suppose you’re implementing a file system that uses a class hierarchy like this one:

class File{public: int Open(const string & path); int Read (char * buff, size_t bytes); int Write (char *buff, size_t bytes); //..};class DiskFile: public File{public: int Defragment();//..};class NetworkFile : public DiskFile{//.. };

Class NetworkFile implements a special type of file that can be stored and accessed remotely. At this stage, the designer faces two problems. First, unlike a local disk file, network files require a more rigorous authorization check to ensure that only authorized users may access them. Secondly, because the file may reside on a remote machine, it’s necessary to overload the Open() member function to support additional types of path names, or, wstring names. A naive designer might include an additional overloaded version of this function like this:

class NetworkFile : public DiskFile{public: int Open(const wstring & path);//seemingly overloading //..};

This code compiles okay. However, it doesn’t exactly overload File::Open?instead, it hides it:

string path="\usr\image.bmp";NetworkFile nf;nf.Open(path); //compilation error

Here’s the problem: when a compiler employs the overload resolution algorithm, it stops searching at the first scope in which a viable candidate is found. In this example, it finds NetworkFile::Open(const wstring & ) and the search terminates. However, the argument passed to the function is of type string &. Because of the type mismatch the compilation fails.Name Injection
To fix this problem, you have to explicitly inject the name File::Open into the scope of NetworkFile::Open(). This way, any additional function called Open() that you declare in NetworkFile won’t hide File::Open. To do so, use a using-declaration like this:

class NetworkFile : public DiskFile{public: using File::Open; //inject a name into current scope int Open(const wstring & path); //..};

When you add a using-declaration of this kind, make sure that it appears in the public section of the class. Now you can use both overloaded versions of Open() in the derived class:

string path="\usr\image.bmp";wstring wpath=L"\usr\image.bmp";NetworkFile nf, nf2;nf.Open(path); //OK, File::Open(const string &)nf2.Open(wpath); //OK, NetworkFile::Open(const wstring &)

You may add as many overloaded versions of Open() as you like to NetworkFile:

class NetworkFile : public DiskFile{public: using File:Open; //inject name into current scope int Open(const wstring & path); int Open (const char * path); int Open (const wchar_t * path); //..};

Likewise, any class that inherits from NetworkFile can use the same technique to add even more overloaded functions:

class UnixNetworkFile : public NetworkFile{public: using NetworkFile:Open; //inject all overloaded versions int Open(int descriptor);//..};UnixNetworkFile nf1, nf2, nf3;nf.Open(path);nf.Open(wpath);nf.Open(2); //opens stderr

Controlling Access Type
A using-declaration also enables you to change the access type of a base class’s member in a derived class. Consider a ReadOnly class that enables users to read a file but not to change it. You may need to change the access type of Write() to private. This can be accomplished by adding a using-declaration to the private section of the class:

class ReadOnly: public File{private: //change the access of File::Write using File::Write;};

Consequently, ReadOnly objects cannot invoke this member function:

ReadOnly ro;ro.Write(mybuff);//error: Write() is not accessible

The Buck Stops Here
Each derived class can override a previous access type. For example, if you have a member function f() declared public in class A, and a derived class D which changes the access type of f() to private:

class A{public: int f();protected: int g();};class D: public A{private using A::f(); //OK, f() is now private};

A class derived from D may override the access type of f() once again:

class E : public D{public using A::f(); //OK, f() is public again};

However, you cannot grant a more permissive access type than the one originally specified in the member’s declaration. For example, the member function g() is declared protected in A. Class F that is derived from A can change g()‘s access to private. A class derived from F may subsequently change g()‘s access back to protected. However, none of them can change g()‘s access type to public. This restriction ensures that the using-declaration facility doesn’t violate the fundamental aspects of the C++ object model.

Share the Post:
XDR solutions

The Benefits of Using XDR Solutions

Cybercriminals constantly adapt their strategies, developing newer, more powerful, and intelligent ways to attack your network. Since security professionals must innovate as well, more conventional endpoint detection solutions have evolved

AI is revolutionizing fraud detection

How AI is Revolutionizing Fraud Detection

Artificial intelligence – commonly known as AI – means a form of technology with multiple uses. As a result, it has become extremely valuable to a number of businesses across

AI innovation

Companies Leading AI Innovation in 2023

Artificial intelligence (AI) has been transforming industries and revolutionizing business operations. AI’s potential to enhance efficiency and productivity has become crucial to many businesses. As we move into 2023, several

data fivetran pricing

Fivetran Pricing Explained

One of the biggest trends of the 21st century is the massive surge in analytics. Analytics is the process of utilizing data to drive future decision-making. With so much of

kubernetes logging

Kubernetes Logging: What You Need to Know

Kubernetes from Google is one of the most popular open-source and free container management solutions made to make managing and deploying applications easier. It has a solid architecture that makes

ransomware cyber attack

Why Is Ransomware Such a Major Threat?

One of the most significant cyber threats faced by modern organizations is a ransomware attack. Ransomware attacks have grown in both sophistication and frequency over the past few years, forcing

data dictionary

Tools You Need to Make a Data Dictionary

Data dictionaries are crucial for organizations of all sizes that deal with large amounts of data. they are centralized repositories of all the data in organizations, including metadata such as