I am doing C++ from 2 years or so , I say why we need constructors in class and not in structures , and why we cant do constructor overloading in structure...
why we need constructors in class
We don't.
// Perfectly valid
class Foo
{
public:
int x
};
why we cant do constructor overloading in structure...
We can.
// Look, ma!
struct Bar
{
Bar operator+(const Bar& other);
};
I don't know where you heard these claims but it certainly wasn't from trying it out.
A user-defined type declared with the keyword struct is a class.
The only difference between struct and class in C++ is visibility; a struct defaults to public while a class defaults to private.
Once you get past that initial visibility, however, they are indistinguishable. A struct is a class with default public visibility.
These two pieces of code have exactly the same effect.
struct MyClass {
MyClass(int i) : m_i(i) {}
int getI() const { return m_i; }
void setI(int i) { m_i = i; }
private:
int m_i;
};
// is exactly the same as
class MyClass {
public:
MyClass(int i) : m_i(i) {}
int getI() const { return m_i; }
void setI(int i) { m_i = i; }
private:
int m_i;
};
or put another way
class MyClass {
int m_i;
public:
MyClass(int i) : m_i(i) {}
int getI() const { return m_i; }
};
struct MyClass {
private:
int m_i;
public:
MyClass(int i) : m_i(i) {}
int getI() const { return m_i; }
};
Related
Consider the following classes,
template <class L>
class A {
public:
A(L l) : _l(l) {}
private:
L _l;
};
class B {
public:
B(int x) : _x(x), _a([this]() { return _x; }) {}
private:
int _x;
A<???> _a;
};
I am not sure how to specify the type at ???. std:: function<int()> works, but to my knowledge, this implies virtual function calls (of course, this does not have to be bad, but it would be interesting how to do this properly).
Rather than a lambda, you can use a function object that's roughly equivalent.
template <class L>
class A {
public:
A(L l) : _l(l) {}
private:
L _l;
};
class B {
struct GetX
{
int operator()() const { return _b->_x; }
B * _b;
};
public:
B(int x) : _x(x), _a(GetX{ this }) {}
private:
int _x;
A<GetX> _a;
};
I need a static analyzer that will find uninitialized variables members/variables... of a templated class type.
Can any analyzer do this? I tried clang/cppcheck and a couple of others with no luck.
Here is my test code:
enum class ViewMode
{
One = 1,
Two = 2,
Three = 3,
Four = 4
};
class TestClass {
public:
TestClass() {}
};
template<typename T, bool C = std::is_copy_constructible<T>::value>
class TemplateTest
{
public:
TemplateTest() {}
TemplateTest(const T& value)
: value_(value)
{}
TemplateTest(const TemplateTest&) = delete;
TemplateTest(TemplateTest<T, C>&& rhs)
: value_(std::move(rhs.value_))
{}
TemplateTest(T&& value)
: value_(std::move(value))
{}
private:
T value_;
};
class StaticAnalysisTest {
public:
StaticAnalysisTest() {}
void DoSomething() {
}
private:
ViewMode viewMode_; //this uninitialized warning is found
TemplateTest<ViewMode> viewMode2_; //this one is not
};
I have further distilled the problem to:
class Foo
{
private:
int m_nValue;
public:
Foo() {};
Foo(int value) : m_nValue(value) {}
int GetValue() { return m_nValue; }
};
class Bar
{
public:
Bar(){}
void DoSomething() {
Foo foo;
}
};
This does not generate an unitialized variable warning, but when I comment out:
//Foo(int value) : m_nValue(value) {}
it does
Thank you for evaluating Cppcheck. A warning is given for the second example, in case you add the --inconclusive flag, for example:
class Foo
{
private:
int m_nValue;
public:
Foo() {};
explicit Foo(int value) : m_nValue(value) {}
int GetValue() const
{
return m_nValue;
}
};
class Bar
{
public:
Bar() {}
static void DoSomething() {
Foo foo;
}
};
The output from Cppcheck
$ cppcheck --enable=all --inconclusive uninitmembervar.cpp
[uninitmembervar.cpp:6]: (warning, inconclusive) Member variable 'Foo::m_nValue' is not initialized in the constructor.
I'm currently reading C++ Primer and am at the point of class friends and member function friends and I'm having trouble figuring out how to get the code that has the following pseudoform to work:
class B;
class A {
public:
A(int i): someNum(i) { }
private:
int someNum;
friend void B::someMemberFunction(Args); // Compile error: Incomplete Type
};
class B {
public:
void someMemberFunction(Args) { /* doStuff */ }
private:
vector<A> someVector { A(5) };
};
If you try to compile in this form it gives the incomplete type error on the friend line. So the solution is to move the class B definition above class A:
class A;
class B {
public:
void someMemberFunction(Args) { /* doStuff */ }
private:
vector<A> someVector { A(5) }; // Compile error: Incomplete Type
};
class A {
public:
A(int i): someNum(i) { }
private:
int someNum;
friend void B::someMemberFunction(Args);
};
However now on the vector line, it doesn't know how to create an object of type A, since A has yet to be defined. So then A needs to be defined before B. But now we've arrived back at the original problem. I think this is called circular dependency? I don't know how to fix this with forward declarations.
Any help would be appreciated. Thanks.
I think you will either have to make the whole of class B a friend (which removes a dependency in A anyway so it's probably a good thing), or use a constructor instead of the in-class initializer.
class B;
class A {
public:
A(int i): someNum(i) { }
private:
int someNum;
friend class B;
};
class B {
public:
void someMemberFunction() { /* doStuff */ }
private:
vector<A> someVector { A(5) };
};
Or this
class A;
class B {
public:
B();
void someMemberFunction() { /* doStuff */ }
private:
vector<A> someVector;
};
class A {
public:
A(int i): someNum(i) { }
private:
int someNum;
friend void B::someMemberFunction();
};
B::B(): someVector{A(5)} { }
I want to write a function that works for any derived classes in a certain hierarchy, without modifying the abstract class input parameter:
class A {
public:
A(int val): m_i(val) { }
virtual void add(int i) = 0;
int m_i;
};
class B: public A {
public:
B(int val): A(val) { }
B(): A(0) { }
virtual void add(int i) { m_i += i; }
};
class C: public A {
public:
C(int val): A(val) { }
C(): A(0) { }
virtual void add(int i) { m_i += i*2; }
};
int f(const A& base_class)
{
// how to create a concrete copy of class base_class?
base_class.add(5);
}
Here f() should work for both B and C, but I can't create a copy of the concrete class because I don't know the actual type, unless I use dynamic_cast.
Is there another approach to solve this problem or should just use dynamic_cast?
The typical approach commonly known as the virtual constructor idiom is to define another virtual method for cloning the concrete class, make it virtual in the abstract base, and call it as needed to produce instances of the desired class without knowing its type:
class A {
public:
A(int val): m_i(val) { }
virtual void add(int i) = 0;
virtual A* clone() const = 0; // Override in derived classes to return new B/C
int m_i;
};
It is not clear from your question why you even need to make a copy.
However, if you do, you could have a clone() method:
class A {
public:
virtual A* clone() const = 0;
};
class B: public A {
public:
virtual B* clone() const { return new(*this); }
};
class C: public A {
public:
virtual C* clone() const { return new(*this); }
};
The problem is that you are passing const A& but add is not a const method if you take away the const modifier then this works:
int f(A& base_class)
{
// how to create a concrete copy of class base_class?
base_class.add(5);
///Need a return here
}
I am using gcc and the error that really tells you what is going is this:
error: no matching function for call to 'A::add(int&) const'
base_class.add(a); ^^^^^
no known conversion for implicit 'this' parameter from 'const A*' to 'A*'
^^^^^^^^
Based on your response the other option is make m_i mutable and make the member methods const like so:
class A {
public:
A(int val): m_i(val) { }
virtual void add(int i) const = 0;
protected:
mutable int m_i;
};
class B: public A {
public:
B(int val): A(val) { }
B(): A(0) { }
virtual void add(int i) const { m_i += i; }
};
class C: public A {
public:
C(int val): A(val) { }
C(): A(0) { }
virtual void add(int i) const { m_i += i*2; }
};
int f(const A& base_class)
{
base_class.add(5) ;
//Need a return here
}
I want to create 2 kind of classes.
the classes will have similar function "set", but the set funct will get "int" in class B and double in class C. (A is abstract calss but it does not require).
What do I need to do?
class A{
int x;
public:
A (int t=1): x(t){}
virtual void set ()=0;
}
class B: public A{
int y;
public:
virtual void set (int y);
};
class C: public A{
double y;
public:
virtual void set (double y);
};
void main ()
{
B b; //error
C c; //error
}
Create a single template class and instantiate which ever you need at the time, or typedef B and C from the template class:
template< typename T > class A
{
public: A() : mValue() {}
void Set( T value ) { mValue = value; }
private: T mValue;
};
typedef A< int > B;
typedef A< double > C;
There are pretty many variants to solve this, but first of all, virtual function has to have the same signature (there could be an exception, but that's irrelevant for your case). So solution is to have and argument(s) that will solve all cases. There are variants:
Pass all variants to the function, and use only particular one:
class A {
public:
virtual void set( int, double ) = 0;
};
class B {
int y;
public:
virtual void set( int val, double ) { y = val; }
};
class C {
double y;
public:
virtual void set( int , double val ) { y = val; }
};
This is not very good solution and does not scale well, so we can use union:
Union Arg {
int i;
double d;
};
class A {
public:
virtual void set( Arg a ) = 0;
};
// derived classes are trivial, so omitted
Union is not type safe, so we can use boost::variant instead
Another solution to have another hierarchy for parameter:
struct Arg {
virtual ~Arg();
};
struct IntArg : Arg {
int m_value;
};
struct DoubleArg : Arg {
double m_value;
};
class A {
virtual void set( const Arg &a ) = 0;
};
class B {
int y;
public:
virtual void set( const Arg &a ) { y = dynamic_cast<const IntArg &>( a ).m_value; }
};
class C {
double y;
public:
virtual void set( const Arg &a ) { y = dynamic_cast<const DoubleArg &>( a ).m_value; }
};
You can use static_cast and then you will not need virtual destructor in Arg, but that is less safe.
These are only some variants, there could be much more, which one suits you best you can only decide based on your program requirements.
Ditch the inheritance and virtual thing. You can't easily access a statically unknown type result via a virtual function. So:
class A
{
private:
int x_;
public:
A( int const t = 1 ): x_( t ) {}
};
class B
: public A
{
private:
int y_;
public:
void set( int const y );
};
class C
: public A
{
private:
double y_;
public:
void set( double const y );
};
int main ()
{
B b; // OK
C c; // OK
}
Note the semicolon at the end of class A and the int main instead of void main.
Such details matter.
Otherwise you can send people who want to help you, on long wild goose chases. And you don't want that, do you? So, make sure the code you post has been accepted by a compiler, except possibly for the troublesome parts that you want to show do not compile.
The trick is to find common parts of B and C, and put them to base class. The stuff that is different should go to constructor parameter of the derived class:
class A {
virtual std::string get() const=0;
virtual void set(std::string s)=0;
};
class B : public A { B(int a) : a(a) { } int a; };
class C : public A { C(float b) : b(b) { } float b; }
To implement the functions, you'll need the following:
void B::set(std::string s) {
stringstream ss(s);
ss >> a;
}
void C::set(std::string s) {
stringstream ss(s);
ss >> b;
}
The functions look the same, but are actually calling different operator>>.