Why Can't Redefine Type Names in Class in C++

Why can't redefine type names in class in C++?

This is not unique to types. [basic.class.scope]/2:

A name N used in a class S shall refer to the same declaration in its
context and when re-evaluated in the completed scope of S. No
diagnostic is required for a violation of this rule.

The reason is that name lookup in class scope is a little special. Consider:

using Foo = int;

struct X {
Foo a; // ::Foo, i.e., int
void meow() {
Foo b = a; // X::Foo; error: no conversion from int to char*
}
using Foo = char*;
};

Name lookup in member function bodies considers all class members, whether declared before or after the member function (otherwise, a member function defined in a class definition wouldn't be able to use a data member declared later in the class). The result is that you get two Foos with different meanings, even though they both lexically precede the class member Foo's declaration. This can easily lead to extremely confusing and brittle code, and so the standard bans it.

Why can't I make a external type appear like an inner type in c++?

This is not allowed because of the rule [basic.scope.class]/3:

A name N used in a class S shall refer to the same declaration in its context and when re-evaluated in the completed scope of S. No diagnostic is required for a violation of this rule.

When you do typedef Inner Inner;, you're violating this rule. The first time Inner appears on that line, it is a use of the name, and is found to refer to the declaration ::Inner. But once the class is completely defined, Inner now refers to the typedef declaration. So the program is ill-formed NDR (GCC is nice enough to give you a diagnostic).

You need to change it to:

typedef ::Inner Inner;

Now, the unqualified name Inner is not being used anymore; instead you are using the qualified name ::Inner, and its meaning stays the same after the typedef, so there should be no issue.

Repeated typedefs - invalid in C but valid in C++?

Why does this compile in C++?

Because the C++ Standard explicitly says so.

Reference:

C++03 Standard 7.1.3 typedef specifier

§7.1.3.2:

In a given non-class scope, a typedef specifier can be used to redefine the name of any type declared in that scope to refer to the type to which it already refers.

[Example:

typedef struct s { /* ... */ } s;

typedef int I;

typedef int I;

typedef I I;

—end example]

Why does this fail to compile in C?

typedef names have no linkage and C99 standard disallows identifiers with no linkage specification to have more than one declaration with the same scope and in the same name space.

Reference:

C99 Standard: §6.2.2 Linkages of identifiers

§6.2.2/6 states:

The following identifiers have no linkage: an identifier declared to be anything other than
an object or a function; an identifier declared to be a function parameter;
a block scope
identifier for an object declared without the storage-class specifierextern.

Further §6.7/3 states:

If an identifier has no linkage, there shall be no more than one declaration of the identifier (in a declarator or type specifier) with the same scope and in the same name space, except for tags as specified in 6.7.2.3.

Class Type Redefinition C++

add include guard to your header file

#ifndef SHAPE_H
#define SHAPE_H

// put your class declaration here

#endif

And the way you initialize member mColor is incorrect. You can't assign NULL to string type

Shape::Shape(const string& color) : mColor(color) {
}

Add virtual destructor to Shape class as it serves as a base with virtual functions.

Also, do NOT use using directive in header file.

C library - use in C++: redefinition, different type modifiers

Here's what your MCVE should look like:

typedef struct T *T;

This is a complete, one-line source file that reproduces the issue and has no dependencies. No macros, no headers, no unnecessary code.

g++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
main.cpp:1:19: error: conflicting declaration 'typedef struct T* T'
typedef struct T *T;
^
main.cpp:1:16: note: previous declaration as 'struct T'
typedef struct T *T;
^

The reason it works in C is that T was not already the name of a struct; you needed the struct prefix.

In C++, this is not true, because the struct prefix wasn't required in the first place. As soon as you have declared that T is a class (which, confusingly, you did in the typedef itself!), you can't just give some other type (the one you're trying to create with the typedef) the same name.

It's rather bizarre what you're doing anyway, making CSV_T mean struct CSV_T*. I suggest simply not doing this.

If you were simply sticking with a typedef struct CSV_T CSV_T then this would work in both languages, but trying to make a different type with the same name just isn't going to work.

Class inheritance and redefining type of members c++

You cannot change the type of the vector in the base class simply by deriving it. A derived class has all the members of the base class, AS WELL AS its own members.

In your code, the derived class as a vector<int> AND a vector<bool>. The Print function that gets called is the base class's Print function, since the derived class doesn't implement its own. The base class's Print function prints the vector<int>.

You need to use templating instead of inheritance. You can do something like:

template <class T>
class Generic {
public:
std::vector<T> vec;

void Print() { std::cout << vec[0]; }

};

int main() {
Generic<bool> * test = new Generic<bool>;
test->vec.push_back(5);
test->Print();
system("PAUSE");
}

In the above code, Generic is a class that holds a vector of T's (where T could be int, bool, whatever). You instantiate a class of a particular type by specifying the type, e.g. Generic<bool>. Generic<bool> is different from Generic<int>, which is different from Generic<double>, etc. in the same way that vector<int> is different from vector<bool>, etc.

C++ 'class' type redefinition

The issue is that you are defining the class twice just as the compiler is telling you. In the cpp you should provide the definitions of the functions like so:

MyClass::MyClass() {
//my constructor
}

or

void MyClass::foo() {
//foos implementation
}

so your cpp should look like:

void CirleObje::setCol(float r, float g, float b)
{
rVal = r;
gVal = g;
bVal = b;
}

void CircleObje::setCoord(int x, int y)
{
xCor = x;
yCor = y;
}

...

And all the class variables should be defined in the .h file inside of your class.

Why am I getting this redefinition of class error?

You're defining the class in the header file, include the header file into a *.cpp file and define the class a second time because the first definition is dragged into the translation unit by the header file. But only one gameObject class definition is allowed per translation unit.

You actually don't need to define the class a second time just to implement the functions. Implement the functions like this:

#include "gameObject.h"

gameObject::gameObject(int inx, int iny)
{
x = inx;
y = iny;
}

int gameObject::add()
{
return x+y;
}

etc



Related Topics



Leave a reply



Submit