Home  >  Article  >  Backend Development  >  Why do public members of a base class become invisible when inheriting a class template, and what are the solutions to this problem?

Why do public members of a base class become invisible when inheriting a class template, and what are the solutions to this problem?

Susan Sarandon
Susan SarandonOriginal
2024-11-02 15:13:30259browse

Why do public members of a base class become invisible when inheriting a class template, and what are the solutions to this problem?

Avoiding Public Member Invisibility and Code Bloat in Inherited Class Templates

Object-oriented programming relies on the inheritance of protected and public class members. In non-templated environments, this inheritance is straightforward. However, when introducing class templates, a fundamental issue arises: public members of the base class become invisible to the derived class template.

The Problem

Consider the following example:

<code class="cpp">class CBase
{
public:
    int Fn1(void) { ... }
};

class CDerived : public CBase
{
public:
    int FnSum(void) { ... CBase::Fn1(); ... }
};</code>

When templating this code, the Fn1() member of CBase disappears from the perspective of CDerived:

<code class="cpp">template<unsigned int BYTES>
class CBase
{
public:
    int Fn1(void) { ... }
};

template<unsigned int BYTES>
class CDerived : public CBase<BYTES>
{
public:
    int FnSum(void) { ... Fn1(); ... } // Error: Fn1 not found!
};</code>

Solutions

Various solutions exist to address this issue:

Solution 1 (Verbose Prefixing):

<code class="cpp">int FnSum(void) {
    return CBase<BYTES>::Fn1() + CBase<BYTES>::Fn2() + CBase<BYTES>::Arr[0];
}</code>

However, this approach introduces excessive code bloat when referencing multiple members.

Solution 2 (Verbose "this->" Prefixing):

<code class="cpp">int FnSum(void) {
    return this->Fn1() + this->Fn2() + this->Arr[0];
}</code>

Similar to Solution 1, but slightly less verbose.

Solution 3 (Using Statement):

<code class="cpp">using CBase<BYTES>::Arr;
using CBase<BYTES>::Fn1;
using CBase<BYTES>::Fn2;</code>

This allows direct access to CBase members without additional prefixing.

Solution 4 (Permissive Mode):

<code class="cpp">// Compiler flags: /permissive- (MSVC), -fpermissive (GCC/Cl), -fno-implicit-templates (Clang)</code>

Disables strict C compliance, resolving the issue but may introduce portability concerns.

A Better Solution

While Solution 3 is cleaner than the others, it still requires repetitive "using" statements. Macros can simplify this:

<code class="cpp">#include <boost/preprocessor.hpp>

#define USING_ONE(r, base, member) using base::member;

#define USING_ALL(base, ...) BOOST_PP_SEQ_FOR_EACH(USING_ONE, base, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__))

#define USING_CBASE(param) USING_ALL(CBase<param>, Arr, Fn1, Fn2, Fn3, Fn4, Fn5)</code>

In the derived class:

<code class="cpp">USING_CBASE(BYTES); // Makes all mentioned CBase members directly accessible</code>

This approach significantly reduces code bloat and duplication.

The above is the detailed content of Why do public members of a base class become invisible when inheriting a class template, and what are the solutions to this problem?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn