Is it a concept or just my VC compiler?

Hi,

During developing a few classes for a product, I came across a weird error compiler showed.

So I created a small c++ prototype to check it out. please consider following code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>
#include <string>

class base
{
public:
    void write( const std::string& one, const std::string& two )
    {
        std::cout << "base::Write2";
    }
    void write( const std::string& one, const std::string& two, const std::string& three )
    {
        std::cout << "base::Write3";
    }
};

class derrived : public base
{
public:
    void write( const std::string& one, const std::string& two )
    {
        std::cout << "derrived::Write2";
    }
};

int main(int argc, char *argv[])
{
    derrived d;
    d.write( "one", "two");
    d.write( "one", "two", "three" );
}


My compiler shows me following error:

 
line 30: error C2660: 'derrived::write' : function does not take 3 arguments


I am wondering why? Which c++ concept have I forgotten? Please help me recollect or understand why this happening?
Interesting ... I get the same problem when compiling the code with GCC.

If you change line 30 to d.base::write( "one", "two", "three" ); it will "work".

EDIT: Some googling and I found that if you add using base::write; to the derrived class definition in your code it also works. I'm not sure why it has to be done this way.
Last edited on
I'm not sure why it has to be done this way.
The reason is the good old ugly information hiding concept of C/C++. write in the derrived class hides consequently all write functions in the base class
If you want to use polymorphism you need to declare the polymorphic functions to be virtual, and access them through a pointer.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>
#include <string>

class base
{
public:
    virtual void write( const std::string& one, const std::string& two )
    {
        std::cout << "base::Write2\n";
    }
    virtual void write( const std::string& one, const std::string& two, const std::string& three )
    {
        std::cout << "base::Write3\n";
    }
};

class derrived : public base
{
public:
    void write( const std::string& one, const std::string& two )
    {
        std::cout << "derrived::Write2\n";
    }
};

int main(int argc, char *argv[])
{
    derrived d;
    base* b = &d;
    b->write( "one", "two");  // this should print 'derrived'
    b->write( "one", "two", "three" );  // this should print 'base'
}

Hope this helps.
> write in the derrived class hides consequently all write functions in the base class

Yes.

When a name is introduced into a nested scope, it hides that name in the outer scope. What is hidden is the name 'write'.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int name(int) { return 8 ; }
int name(double) { return -3 ; }

int main()
{
    int i ;
    {
        i = name(45) ; // ok, ::name(int)
        int name ; // ok. name hides ::name
        i = name(45) ; // error - 'name' is an int, not a function
    }
    {
        i = name(4.5) ; // overload resolves to ::name(double)
        extern int name(int) ; // declare name(int), hides ::name
        i = name(4.5) ; // name is not overloaded; calls ::name(int)
    }
}
Hi !

Thank you all for your responses. I have understood now.

But now I have a new question regarding this same concept.
Why this concept itself? Or what may be reasons behind this concept?
Every declaration is declared in some declarative region. A declaration in a inner declarative region hides the declaration in an outer declarative region with the same name. For example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>

int a = 1;

int main()
{
   std::cout << "a = " << a << std::endl;

   int a = 2;
   std::cout << "a = " << a << std::endl;

   {
      int a = 3;
      std::cout << "a = " << a << std::endl;
   }

   std::cout << "a = " << a << std::endl;
   std::cout << "::a = " << ::a << std::endl;
}




By the way your original example could be compiled if you called the function with three parameters the following way

int main(int argc, char *argv[])
{
derrived d;
d.write( "one", "two");
d.base::write( "one", "two", "three" );
}

Last edited on
> Why this concept itself? Or what may be reasons behind this concept?

The rationale for this design decision is explained in D&E http://www2.research.att.com/~bs/dne.html

For instance, without it,
1
2
3
4
5
template < typename T > struct A : public T
{
    void foo(int) // ???
    { /* .... */ }
};

would be fraught with uncertainty and speculation.
Topic archived. No new replies allowed.