C++ Name Hiding | 'Function Not Visible' Name Hiding Problem Solution

C++ Name Hiding | 'Function Not Visible' Name Hiding Problem Solution

이 글의 핵심

C++ name hiding C++, "function, visible", Introduction: "Base class function not visible" explained in detail with practical examples.

Introduction: “Base Class Function Not Visible"

"Overload Disappeared”

In C++, defining function with same name in derived class causes name hiding problem where all base class overloads get hidden.

Here is detailed implementation code using C++. Define a class to encapsulate data and functionality. Understand the role of each part while examining the code.

// ❌ Name hiding
class Base {
public:
    void foo(int x) {
        std::cout << "Base::foo(int): " << x << '\n';
    }
    
    void foo(double x) {
        std::cout << "Base::foo(double): " << x << '\n';
    }
};

class Derived : public Base {
public:
    void foo(std::string s) {
        std::cout << "Derived::foo(string): " << s << '\n';
    }
};

int main() {
    Derived d;
    d.foo("Hello");  // OK
    d.foo(42);       // ❌ Compile error: no matching function
    d.foo(3.14);     // ❌ Compile error
}

What This Guide Covers:

  • What is name hiding?
  • Solution with using declaration
  • Overloading vs overriding
  • Practical examples

1. What is Name Hiding?

Name Hiding Occurs

Here is detailed implementation code using C++. Define a class to encapsulate data and functionality, ensure stability through error handling. Understand the role of each part while examining the code.

class Base {
public:
    void foo(int x) {
        std::cout << "Base::foo(int)\n";
    }
};

class Derived : public Base {
public:
    void foo(double x) {  // Hides Base::foo(int)
        std::cout << "Derived::foo(double)\n";
    }
};

int main() {
    Derived d;
    d.foo(3.14);  // Derived::foo(double)
    d.foo(42);    // ❌ Compile error
    // error: no matching function for call to 'Derived::foo(int)'
}

Reason: Derived class foo completely hides base class foo.


2. using Declaration

Solution: using Declaration

Here is detailed implementation code using C++. Define a class to encapsulate data and functionality. Understand the role of each part while examining the code.

class Base {
public:
    void foo(int x) {
        std::cout << "Base::foo(int)\n";
    }
    
    void foo(double x) {
        std::cout << "Base::foo(double)\n";
    }
};

class Derived : public Base {
public:
    using Base::foo;  // ✅ Bring base class foo
    
    void foo(std::string s) {
        std::cout << "Derived::foo(string)\n";
    }
};

int main() {
    Derived d;
    d.foo(42);       // Base::foo(int)
    d.foo(3.14);     // Base::foo(double)
    d.foo("Hello");  // Derived::foo(string)
}

3. Overloading vs Overriding

Overloading: Same Name, Different Signature

Below is an implementation example using C++. Define a class to encapsulate data and functionality. Try running the code directly to check its operation.

class MyClass {
public:
    void foo(int x) {}
    void foo(double x) {}      // Overloading
    void foo(std::string s) {} // Overloading
};

Overriding: Redefining Virtual Function

Below is an implementation example using C++. Define a class to encapsulate data and functionality. Understand the role of each part while examining the code.

class Base {
public:
    virtual void foo(int x) {
        std::cout << "Base::foo\n";
    }
};

class Derived : public Base {
public:
    void foo(int x) override {  // Overriding
        std::cout << "Derived::foo\n";
    }
};

Name Hiding vs Overriding

Here is detailed implementation code using C++. Define a class to encapsulate data and functionality. Understand the role of each part while examining the code.

class Base {
public:
    virtual void foo(int x) {
        std::cout << "Base::foo(int)\n";
    }
    
    virtual void foo(double x) {
        std::cout << "Base::foo(double)\n";
    }
};

class Derived : public Base {
public:
    void foo(int x) override {  // Override Base::foo(int)
        std::cout << "Derived::foo(int)\n";
    }
    // Base::foo(double) is hidden!
};

int main() {
    Derived d;
    d.foo(42);    // Derived::foo(int)
    d.foo(3.14);  // ❌ Compile error
}

Solution:

Below is an implementation example using C++. Define a class to encapsulate data and functionality. Try running the code directly to check its operation.

class Derived : public Base {
public:
    using Base::foo;  // ✅ Bring Base::foo(double)
    
    void foo(int x) override {
        std::cout << "Derived::foo(int)\n";
    }
};

Summary

Key Points

  1. Name hiding: Derived class function hides all base overloads
  2. using declaration: Brings base class functions
  3. Overloading: Same name, different signature
  4. Overriding: Redefining virtual function
  5. Solution: Use using Base::func;

When to Use

Use using when:

  • Want to keep base class overloads
  • Derived class adds new overload
  • Need all function variants

Don’t use when:

  • Want to completely replace base function
  • Intentionally hiding base function

Best Practices

  • ✅ Use using declaration for overloads
  • ✅ Use override for virtual functions
  • ✅ Be aware of name hiding
  • ❌ Don’t accidentally hide base functions
  • ❌ Don’t confuse overloading with overriding

Master name hiding for cleaner C++ inheritance! 🚀