Is there any way to redeclare a class to define methods which where only declared this far?
Eg. something like:
class A
{
void a();
void b() {}
}
class A
{
void a() {}
}
instead of
class A
{
void a();
void b() {}
}
A::a() {}
The reason is I created a lot of code with methods defined inside the class defintion, without using headers. I do not had cyclic references up to now, but recently there is need to. I don't like to define bunches of methods by the Type::method syntax, as only very few methods have to be known before the latter definition of the class.
So I like somewhat like a backward declaration, declare or define only a few methods before for cyclic references and define the whole class later.
No, there is no way to redefine a class.
According to the C++ language standard the class definitions is:
class-specifier:
class-head { member-specification_opt }
The standard explicitly says that member specification should be complete within class definition:
Members of a class are data members, member functions (9.3), nested types, and enumerators. The member-specification in a class definition declares the full set of members of the class; no member can be added elsewhere.
Also the standard gives example of redefinition of class:
struct S { int a; };
struct S { int a; }; // error, double definition
is ill-formed because it defines S twice.
Unfortunately there is no way to declare the class again once it is Closed with }.
Only thing you can do is you can inherit and define the method.
class B : public A { a() {} } ;
Related
Sometimes I use foreward declaration for nested classes:
class A;
class B
{
private:
A* object_A;
public:
B(){}
};
The question: What happens if I now use forward declaration of class B (B is declared and defined at this point) for the useage in class C? Does this cause any problems with class B, because it is defined (with implementation of methods etc.) but is used with forward declaration for class C? Does the syntax class B; in the following code-snippet overwrites somehow the previous declared, defined and implemented class B?
class B;
class C
{
private:
B* object_B;
public:
C(){}
};
Does the syntax class B; in the following code-snippet overwrites somehow the previous declared, defined and implemented class B?
Forward declarations are not about overwriting. It is just giving hint to the compiler that the type definition is implemented somewhere. For user defined pointer types, compiler does not require the definition but needs to know what is the type of the object.
I'm getting this strange problem which I don't know why happens. The first and second of the following code snippets compile, while the third does not:
Compiles:
class Foo {
public:
Foo() { Bar(); }
private:
class Bar {};
};
Compiles:
class Foo {
class Bar {}; // Or only forward declare here and define later
public:
Foo(Bar) {}
}
Does not compile:
class Foo {
public:
Foo(Bar) {}
private:
class Bar {};
};
What makes the third fail to compile while the first can?
Normally, in C++, you can only reference declarations that were previously made in the translation unit. However, within a class definition, the definition of member functions are allowed to reference declarations which are made later in the class. Basically, the compiler restructures your in-class definitions so that they work as though they were written just after the class.
But this is only true of the function definitions. The declaration of the function (including parameter types) isn't allowed to do this. They can only reference declarations that have already been made in file order.
So you can do this:
class Test
{
public:
void Func(int x) {Inner foo;}
private:
class Inner {};
};
But not this:
class Test
{
public:
void Func(Inner x) {}
private:
class Inner {};
};
First example does not expose anything about private Bar to the outside, while third does.
Third example is pretty much saying, that there exist some class Foo, which has constructor with single argument of type Bar. But Bar is unknown to the outside. Imagine calling such constructor.
Foo f{Foo::Bar{}};
Will result probably in something like Foo::Bar is inaccessible.
I complied the following code, and get
error: incomplete type ‘AB::B’ used in nested name specifier
class B; //declareation
namespace A
{
class myException():public std::exception
{
public:
myException():std::exception()
{
B::b2(); //error: incomplete type ‘A::B’ used in nested name specifier
}
};
class B()
{
static void b1()
{
throw myException();
}
static void b2()
{
//code
}
};
};
I think I got a circular dependency between these two classes. Is it the reason that cause the error?
How can I get arround the circular dependency?
Thanks a lot
I think I got a circular dependency between these two classes.
Not between the classes themselves; but each has member functions that depend on the other class, so as written there is a circular dependency.
Is it the reason that cause the error?
Yes. Each member function definition has to come after the class that it uses; which is impossible if they are defined in the class.
How can I get arround the circular dependency?
Move the definition of at least one of the member functions out of its class, to a point at which the other class is defined. If these are in a header, intended to be included from multiple source files, then either move the definition to a source file, or to later on in the header with an inline specifier.
For example, you could move the constructor of myexception, leaving just a declaration in the class:
class myException():public std::exception
{
public:
myException(); // OK: no use of incomplete type here
};
and define it either inline, after the definition of B, or in a source file that includes this header:
inline // if defined in a header
myException::myException() // no need to explicitly initialise std::exception
{
B::b2(); // OK: B is complete now
}
First of all,
class B; //declareation
namespace A
{
declares B to be a class in the global namespace, not in namespace A. Hence, the use of
B::b2();
later in the code expects b2 to be a member of the global B. I think you meant to forward declare the B in namespace A. For that, you need to use:
namespace A
{
class B; //declareation
To remove the circular dependencies between the class definitions and the member function implementations, move the member function implementations after the classes have been defined. Then, you don't need the forward declaration of B at all. It won't hurt if it's there, but it's not necessary.
namespace A
{
// Optional.
class B;
// Class definitions without the member function implementations
class myException(): public std::exception
{
public:
myException();
};
class B()
{
public:
static void b1();
static void b2();
};
// Class member function implementations
inline myException::myException(): std::exception()
{
B::b2();
}
inline void B::b1()
{
throw myException();
}
inline void B::b2()
{
//code
}
}
In this point
class B; //declareation
//...
myException():std::exception
{
B::b2(); //error: incomplete type ‘A::B’ used in nested name specifier
}
the compiler does not know whether class B has member b2 because class B is not defined yet. So the compiler issues an error because it does not know what expression b2() means.
Also this statement
myException():std::exception
contains a syntaxical error. I think you mean
myException():std::exception()
You have to define the constructor after the definition of class B.
If only define this method it will have a compiler error.
void classA::testMethod() {
}
And so it must be declared first:
class classA {
void testMethod();
};
Why should these be declared?
I know for common C method methods it is not needed declare, but they can just be defined:
void test() {
}
There are several secondary reasons both objective and subjective (i.e. allows to specify visibility, serves as an interface for the class and probably several others related to compiling and linking phases and TU symbols visibility, not to mention a class is the basic encapsulation unit, with all that implies) but an unquestionable one is that the standard dictates it:
N3797 - class.mfct/p2
A member function may be defined (8.4) in its class definition, in
which case it is an inline member function (7.1.2), or it may be
defined outside of its class definition if it has already been
declared but not defined in its class definition. A member function
definition that appears outside of the class definition shall appear
in a namespace scope enclosing the class definition. Except for member
function definitions that appear outside of a class definition, and
except for explicit specializations of member functions of class
templates and member function templates (14.7) appearing outside of
the class definition, a member function shall not be redeclared.
emphasis mine.
You don't need to declare the method before you define it, but you need to declare class methods in the class. Else it wouldn't be a class method.
That may seem like a contradiction, but a definition is also a declaration. So what this means is that the definition may appear in the class itself:
class A {
void testMethod() { /*...*/ }
};
[edit]
Also, practically speaking, inside the class declaration there are private, protected and public parts. This is needed to for encapsulation. If you could declare methods outside the class, you would lose encapsulation. Anybody could access private members merely by defining extra getters and setters, even when those would not make sense. Class invariants would become meaningless.
It helps encapsulation. If you have a class A
class A {
public:
foo();
bar();
}
You can be sure that only methods foo and bar mess with the private data members of the class. (Or pointer magic or undefined behavior of course)
All of the previous answers are correct as far as they go, but
they fail to point out the reason behind the rule. In C++,
a class definition is closed; you cannot add to it later. This
is necessary for non-static data members, since they determine
the size (and the implicitly generated special functions), but
it is a basic principle in C++ for all class members: not just
data, but functions, types, etc. It is considered essential for
good encapsulation.
This is true for most (but not all) languages which support the
concept of class.
This also explains why it the situation is different for
namespaces (which aren't closed).
Note the use of the qualifier ::. It means
on the left you have a namespace or class identifier
on the right you have a namespace, class, or method / function identifier
So writing void A::testMethod() assumes that there is a class or namespace A defined - this is how C++ is defined. And this applies to
void A::testMethod();
as well as to
void A::testMethod()
{
}
Also note the global namespace where you have indeed nothing at the left of :: as in
void ::testMethod()
{
}
And by definition the global namespace is always defined so the above code defines a function similar to C-style without the qualifier.
Even if it were not mandated by the standard, there are the following two reasons why you need to declare all class methods in the class definition.
You can only declare something as public, private or protected in the class declaration, you can't do so at the method definition in the .cpp file. So what visibility would your free-standing class method have?
If the standard decided to select one of the three as the default (C++ defaults to private), and place that visibility on your method, you now have a scoping problem. Even the most restrictive visibility (private) means that you can use the method in any other member method, including those defined before it in the source file. Without the declaration in the class definition, those earlier functions would not be aware of your free standing method, thus you violate the scoping rules.
In your foo.h header:
class foo
{
public:
foo() {}
virtual ~foo() {}
declaredMethod();
};
In your foo.cpp
foo::declaredMethod()
{
...
freeStandingMethod(); // This should be legal, but it can't work since we
// haven't seen foo::freeStandingMethod() yet
...
}
foo::freeStandingMethod()
{
...
}
Even if you could make this work in the same .cpp file, it's legal to place foo::freeStandingMethod() in a different .cpp file from foo::declaredMethod() at which point this becomes impossible.
This is not an answer, but you might find it informative and fun.
Adding 2 template functions to your class will effectively allow you to call any free function that takes an object of that class as the first parameter:
#include <string>
#include <iostream>
struct puppy {
puppy(std::string name)
: _name(std::move(name))
{}
const std::string& name() const noexcept {
return _name;
}
void set_name(std::string name) {
_name = std::move(name);
}
template<class F, class ...Args>
auto perform(F&& f, Args&&...args) const
-> decltype(f(*this, std::forward<Args>(args)...))
{
return f(*this, std::forward<Args>(args)...);
}
template<class F, class ...Args>
auto perform(F&& f, Args&&...args)
-> decltype(f(*this, std::forward<Args>(args)...))
{
return f(*this, std::forward<Args>(args)...);
}
private:
std::string _name;
};
void woof(const puppy& p) {
std::cout << "puppy " << p.name() << " woofs!" << std::endl;
}
void indented_woof(const puppy&p, size_t indent) {
std::cout << std::string(indent, ' ');
woof(p);
}
void complex_woof(const puppy& p, int woofs)
{
std::cout << "attention!" << std::endl;
for (int i = 0 ; i < woofs ; ++i) {
p.perform(indented_woof, 4);
}
}
std::string name_change(puppy& p, std::string(new_name))
{
auto old_name = p.name();
p.set_name(std::move(new_name));
return old_name;
}
int main()
{
puppy fido { "fido" };
fido.perform(woof);
fido.perform(complex_woof, 10);
auto old_name = fido.perform(name_change, "bonzo");
fido.perform(woof);
std::cout << "changed name from " << old_name << std::endl;
return 0;
}
"Methods" or "member functions" (as is the more common terminology in C++) are part of the class declaration. Since you must declare a C++ class in one single place, you must make sure that all "member functions" (or "methods") are already present in that declaration.
I know for common C method methods it is not needed declare, but they
can just be defined
When you refer a "common C method" in C++, you actually mean a "common function". Note that you can declare classes anywhere you can declare such functions.
Also, note that you can declare a member function with a body. You do not have to separate declaration and definition. I.e. this is perfectly valid:
class A{
void privateMethod() {
// do something here...
}
public:
void publicMethod() {
// do something here...
}
};
why should declare these? I know for common c method, there is no need to declare, instead of it just define it:
There is no method in C, just attribute of an struct, wich can be function Pointeur, then associated to a function addresse.
Furthermore you have to declare it in the class definition for the same reason you do it in C:
The compilateur will transform this pre-declaration into a function pointeur then associate to the said methode int the construction of your object.
If a definition of a C++ class should be transformed to a C struct the code would be like this:
struct Aclass {
void (*Amethode))(int);
}
void Amethode(int) { return (0); }
Aclass primaryObject = {&Amethode};
Aclass* AclassConstructor() {
Aclass* object;
object = malloc(sizeof(Aclass));
memcpy(object, primaryObject, sizeof(Aclass));
return (object);
}
Given the base class A and the derived class B:
class A {
public:
virtual void f() = 0;
};
class B : public A {
public:
void g();
};
void B::g() {
cout << "Yay!";
}
void B::f() {
cout << "Argh!";
}
I get errors saying that f() is not declared in B while trying do define void B::f(). Do I have to declare f() explicitly in B? I think that if the interface changes I shouldn't have to correct the declarations in every single class deriving from it. Is there no way for B to get all the virtual functions' declarations from A automatically?
EDIT: I found an article that says the inheritance of pure virtual functions is dependent on the compiler:
http://www.objectmentor.com/resources/articles/abcpvf.pdf
I'm using VC++2008, wonder if there's an option for this.
Do I have to declare f() explicitly in B?
Yes, you have to declare in the class' definition all virtual function of any base classes that you want to override in the class. As for why: That's just the way the C++ syntax is.
Note that the virtual keyword can be omitted for the declaration of overriding virtual functions:
class base {
virtual void f();
virtual void g();
};
class derived : public base {
virtual void f(); // overrides base::f()
void g(); // overrides base::g()
};
Note: A class declaration is this: class my_class;, while this class my_class { /* ... */ }; is a class definition. There's a limited number of things you can do with a class that's only been declared, but not defined. In particular, you cannot create instances of it or call member functions.
For more about the differences between declaration and definitions see here.
Ok, for the benefit of the "declaration vs. definition" debate happening in the comments, here is a quote from the C++03 standard, 3.1/2:
A declaration is a definition unless it [...] is a class name declaration
[...].
3.1/3 then gives a few examples. Amongst them:
[Example: [...]
struct S { int a; int b; }; // defines S, S::a, and S::b
[...]
struct S; // declares S
—end example]
To sum it up: The C++ standard considers struct S; to be a declaration and struct S { /*...*/ }; a definition. I consider this a strong backup of my interpretation of "declaration vs. definition" for classes in C++.
Yes, in C++ you have to explicitly clarify your intention to override the behavior of a base class method by declaring (and defining) it in the derived class. If you try to provide a new implementation in derived class without declaring it in class definition it will be a compiler error.
The C++ class declaration defines the content of the class. If you do not declare f() in B, it looks like you do not override it. B::f() can be implemented only if you declare it.
In your current code, you are just inheriting the function f() in class B and you do not redefine base class's member in derived class.
Is there no way for B to get all the
virtual functions' declarations from A
automatically?
If you do not mark the function f in A as pure virtual with =0, the function is automatically also present in any subclass.
class A {
public:
virtual void f(); // not =0!
};
class B : public A {
public:
void g();
};
void A::f() {
cout << "I am A::f!";
}
void B::g() {
cout << "Yay!";
}
Now:
B* b = new B();
b->f(); // calls A::f
By declaring a pure virtual function you are stating that your class is abstract and that you want to require all concrete derived classes to have an implementation of that function. A derived class which does not supply an implementation for the pure virtual function is an extension of the abstract base class and is, itself, an abstract class. Trying to instantiate an abstract class is, of course, an error.
Pure virtual functions allow you to define an interface "contract" that you expect all derived classes to adhere to. A client of that class can expect that any instantiated class with that interface implements the functions in the contract.
Another interesting tidbit... you may supply a body for a pure virtual function but it is still pure and must be overridden in a concrete derived class. The advantage to supplying the body is to provide base behavior while still forcing derived classes to implement the function. The overridden functions can then call the base function Base::F() just like other virtual functions. When the body is not defined, calling Base::F() on a pure virtual functions is an error.