I have 2 Classes Namely A and B with following independent declaration
class A {
private:
std::vector<B> vec = {B("X","Y")};
public:
A();
void clear(std::vector<B>::size_type index);
};
class B {
private:
std::string m_first;
std::string m_second;
public:
B() = default;
B(std::string first, std::string second) : m_first(first), m_second(second) {}
// I want the friend below - how to do it?
friend void A::clear(std::vector<B>::size_type index);
};
I want to declare void A::clear(std::vector<B>::size_type index) to be friend of class B. Is it possible in C++? I cannot do forward declaration of B for A as A needs to see B's constructor with 2 arguments.
I'm 99% sure that your requirement to have A::clear as a friend of B is a case of too tight of a coupling. This is friendship misuse. Think of another way of doing it.
Please edit the question and provide the reason why you think you need that friendship. What is exactly the relationship between these classes, what's the use case? Convince us that there's a need for friendship, because I don't see it.
And the best I can tell the signature of B's constructor is wasteful in copying the arguments (by taking them by value). These arguments should be taken by const reference, unless you need a copy to modify within the method/constructor. I've fixed it below.
A needs to see B constructor with 2 arguments .
It doesn't! A doesn't. Only A's constructor does:
#pragma once
#include <string>
#include <vector>
class B;
class A {
private:
std::vector<B> vec;
public:
A();
void clear(std::vector<B>::size_type index);
};
class B {
private:
std::string m_first;
std::string m_second;
public:
B() = default;
B(const std::string &first, const std::string &second) :
m_first(first),m_second(second) {}
friend void A::clear(std::vector<B>::size_type index);
};
inline A::A() : vec{ B("X", "Y") } {}
Another trick is to put A inside of B. But it's wholly unnecessary.
#pragma once
#include <string>
#include <vector>
class B {
private:
std::string m_first;
std::string m_second;
public:
class A {
private:
std::vector<B> vec = {B("X","Y")};
public:
void clear(const std::vector<B>::size_type &index);
};
B() = default;
B(const std::string &first, const std::string &second) :
m_first(first),m_second(second) {}
friend void A::clear(const std::vector<B>::size_type &index);
};
using A = B::A;
You've set things up so the class A needs to be defined before B (so B can declare a member of A as a friend) but simultaneously B needs to be defined before A (so the vec member of A can be initialised using the constructor of B).
This is a circular dependency (definition of A must be before definition of B which must be before the definition of A - ad infinitum).
Declaring a member of a class as a friend is not possible unless that class has been previously defined.
You need to break that circular dependency - either by not having A::clear() as a friend of B, or by not initialising the vec member of A within the class definition (which means you then need to initialise vec solely in the constructor of A).
Alternatively, it is possible to declare A as friend of B without A being previously defined (i.e. a previous declaration of A is sufficient, without making it a definition). So an alternative may be to declare A as a friend of B rather than only A::clear().
This means that B must be defined before A. B can be defined without visibility of the definition of A.
Related
The following classes definitions declare a friend function providing an inline definition for it. I was trying to invoke the friend function from a class method with the same name of the friend function, but in order to make it work I have to access it from the enclosing namespace (which also requires a forward declaration, class C below). Why the name lookup works for class A and it doesn't work in class B? Note that the parameters of B::swap are different from those of its friend function.
#include <utility>
struct A {
A(int x) : v{ x } {}
friend void swap(A& x, A& y) { std::swap(x.v, y.v); }
void swapm(A& other) { swap(*this, other); }
private:
int v;
};
struct B {
B(int x) : v{ x } {}
friend void swap(B& x, B& y) { std::swap(x.v, y.v); }
void swap(B& other) { swap(*this, other); } // <-- This doesn't compile
private:
int v;
};
struct C;
void swap(C& x, C& y);
struct C {
C(int x) : v{ x } {}
friend void swap(C& x, C& y) { std::swap(x.v, y.v); }
void swap(C& other) { ::swap(*this, other); }
private:
int v;
};
int main()
{
A a1{ 1 }, a2{ 2 }; swap(a1, a2); a1.swapm(a2);
B b1{ 3 }, b2{ 4 }; swap(b1, b2); b1.swap(b2);
C c1{ 5 }, c2{ 6 }; swap(c1, c2); c1.swap(c2);
}
Whether it's a good idea or not, here's an explanation of why it's failing:
The compiler uses several different phases of processing to figure out what your program says. The reason that class B doesn't compile is because the failure that's occurring happens before the friend would be noticed. Let me explain:
When the compiler gets to the point where it's trying to figure out what swap means, it does a name lookup. It uses specific rules that specify where it should look. This is simplified, but basically it first looks for symbols defined in local scope, then in class scope, and then in enclosing (namespace, etc) scopes. It finds the one defined in class scope, and stops looking. That swap does not take those 2 parameters, so it the compilation fails.
The friend declaration, which allows the free function to access B's internals, acts as an additional declaration for the swap function that you've declared in the global namespace. These declarations would be considered by the compiler if it got to the point in name lookup where it was considering functions in the global namespace. In class B, the compiler has already stopped processing before it gets to this stage. (And the friend declaration would be necessary in an even later phase, when the compiler is working on compiling a version of the swap function that works with B objects, and wants to figure out, "in this function called swap that can take these 2 parameters; can I access B's internals?")
In class A, you're using a different name. The name lookup phase doesn't succeed until it locates your free swap function. In class C, you've given the name-lookup specific instructions, "hey, when you're looking up swap, look in global-namespace scope, and ignore the ones in local- and class-scope that you might find."
(Note: description of name-lookup and friend updated after #PeteBecker's comment.)
inline friend? Why not static in this case? And not friend? And then create a global one that calls the static. For me, this is a bad design more than an actual problem.
The method swap should be the one doing the work instead of the friend (because no need for a friend anymore):
struct C {
C(int x) : v{ x } {}
void swap(C& other) { std::swap(this->v, other.v); }
private:
int v;
};
void swap(C& x, C& y)
{
x.swap(y);
}
I am trying to implement virtual class with pure virtual method and 'copy and swap' idiom, but I've encountered some problems. Code won't compile because I am creating instance in the assign operator of the class A which contains pure virtual method.
Is there a way how to use pure virtual method and copy and swap idiom?
class A
{
public:
A( string name) :
m_name(name) { m_type = ""; }
A( const A & rec) :
m_name(rec.m_name), m_type(rec.m_type) {}
friend void swap(A & lhs, A & rhs)
{
std::swap(lhs.m_name, rhs.m_name);
std::swap(lhs.m_type, rhs.m_type);
}
A & operator=( const A & rhs)
{
A tmp(rhs);
swap(*this, tmp);
return *this;
}
friend ostream & operator<<( ostream & os,A & x)
{
x.print(os);
return os;
}
protected:
virtual void print(ostream & os) =0;
string m_type;
string m_name;
};
class B : A
{
public:
B(string name, int att) :
A(name),
m_att(att)
{
m_type="B";
}
B( const B & rec) :
A(rec),
m_att(rec.m_att) {}
friend void swap(B & lhs, B & rhs)
{
std::swap(lhs.m_att, rhs.m_att);
}
B & operator=( const B & rec)
{
B tmp(rec) ;
swap(*this, tmp);
return *this;
}
private:
virtual void print(ostream & os);
int m_att;
};
Error message:
In member function ‘A& A::operator=(const A&)’:|
error: cannot declare variable ‘tmp’ to be of abstract type ‘A’|
because the following virtual functions are pure within ‘A’:|
virtual void A::print(std::ostream&)|
As your compiler informs you, you cannot create a variable of abstract type. There is no way of dancing around that.
This leaves you three main options:
Stop using pure virtual functions
First, you could just get rid of the pure virtual methods and provide a little stub in each of them that calls std::terminate, which would obviously break compile time detection of whether all (former) pure virtual methods are overridden in all derived classes.
This will cause slicing, since it will only copy the base class and everything that makes out the derived class is lost.
Use a stub class w/o pure virtual functions
Similar to that, you could create a derived class that implements all virtual methods with simple stubs (possibly calling std::terminate), and is used only used as a "instantiatable version of the base class".
The most important part to implement for this class would be a constructor that takes a const reference to the base class, so you can just use it instead of copying the base class. This example also adds a move constructor, because I am a performance fetishist.
This causes the same slicing problem as the first option. This may be your intended result, based on what you are doing.
struct InstantiatableA : public A {
InstantiatableA(A const& rhs) : A(rhs) { }
InstantiatableA(A&& rhs) : A(::std::move(rhs)) { }
void print(ostream&) override { ::std::terminate(); }
};
A& A::operator=(InstantiatableA rhs) {
using ::std::swap;
swap(*this, rhs);
return *this;
}
Note: This is really a variable of type A, although I said it could not be done. The only thing you have to be aware is that the variable of type A lives inside a variable of type InstantiatableA!
Use a copy factory
Finally, you can add a virtual A* copy() = 0; to the base class. Your derived class B will then have to implement it as A* copy() override { return new B(*this); }. The reason dynamic memory is necessary is because your derived types may require arbitrarily more memory than your base class.
You're just facing the fact that inheritance works awkwardly with copy semantics.
For instance, imagine you found a trick to pass the compiling phase, what would mean (following example uses assignment but the issue is the same with a copy) :
// class A
// a class B : public A
// another class C : public A inheriting publicly from A
// another class D : public B inheriting publicly from B
B b1;
C c1;
D d1;
// Which semantic for following valid construction when copy/assignment is defined in A ?
b1 = c1;
b1 = d1;
A &ra = b1;
B b2;
// Which semantic for following valid construction when copy/assignment is defined in A ?
ra = b2;
ra = c1;
ra = d1;
CRTP is a choice:
template<typename swappable>
struct copy_swap_crtp{
auto& operator=(copy_swap_crtp const& rhs){
if (this==std::addressof(tmp))
return *this;
swappable tmp{rhs.self()};
self().swap(tmp);
return *this;
};
auto& operator=(copy_swap_crtp && rhs){
self().swap(rhs.self());
return *this;
};
protected:
auto& self(){return *static_cast<swappable*>(this);};
//auto& self()const{return *static_cast<swappable const*>(this);};
};
user class:
struct copy_swap_class
: copy_swap_crtp<copy_swap_class>
{
copy_swap_class(copy_swap_class const&);
void swap(copy_swap_class&);
};
cheers,
FM.
The compiler is right. The class A is abstract class, therefore you can not create instances of it in the operator=.
In B, you just declared the print function, but you didn't implement it. Meaning, you will get linking errors.
By implementing it, it compiles fine (if we ignore various warnings) :
void B::print(ostream & os )
{
os << m_att;
}
by the way :
B inherits privately from A, is that what you wanted?
order of initialization in A's copy constructor is wrong
you initialized m_type in A's constructor's body and not in the initialization list
I have codes like this:
class A{ // declaration is simplified
virtual void FNC1();
};
bool compare(S s1,S s2){
return s1<s2;
}
void A::FNC1(){
iterator it;
sort(it.begin(),it.end(),compare);
}
class B : public A{
virtual void FNC1();
};
void B:FNC1(){
iterator it;
// do something different
sort(it.begin(),it.end(),compare);
}
So I used class B to inherit class A and overrode the function FNC1(), but the problem is, as in the std::sort() function, the 3rd variable should really be a function, and such function is always directly declared. I really want to know what to do to avoid the copy and paste and make B directly inherit this function. I have tried to put the compare() function as a member function of A, and it won't compile:
sort(it.begin(), it.end(), this->compare);
I tried to include the compare function into a separate header file, and it says I cannot declare it. How could I correctly make B inherits this function? Because, in practical, I have 3 classes all need to reuse A's codes and the compare function is really a complicated one.
Your problem is that function compare is defined in the header, meaning that you have its body there in addition to its signature. If you include the header in two places, the compiler will complain about multiple definitions. You should only have the declaration in the header, and the definition in a .cpp file.
This should go into A's header, let's call it a.h
bool compare(S s1,S s2);
This should go into a.cpp
bool compare(S s1,S s2){
return s1<s2;
}
By the way, just to clear up the terminology, you cannot inherit a non-member function. You can use any non-member function anywhere, as long as you include its declaration and link against its object file.
You could make the compare function a static member function of the base class, rather than making it free-standing:
class A{ // declaration is simplified
virtual void FNC1();
public:
static bool compare(const A& s1, const A& s2) {
return ...; // The logic behind your compare function goes here
}
};
You can use the function like this:
sort(it.begin(), it.end(), A::compare);
You are on the right track. You can simply reuse the compare function, you don't need to modify it or try to "inherit" it or any such thing.
The following should compile and run without error.
#include <algorithm>
#include <vector>
struct S { int i; };
class A{ // declaration is simplified
public:
virtual void FNC1();
};
bool compare(const S& s1,const S& s2){
return s1.i < s2.i;
}
void A::FNC1(){
std::vector<S> v;
std::sort(v.begin(),v.end(),compare);
}
class B : public A{
public:
virtual void FNC1();
};
void B::FNC1(){
std::vector<S> v;
// do something different
std::sort(v.begin(),v.end(),compare);
}
int main () { A a; B b; a.FNC1(); b.FNC1(); }
The reason it won't compile if you make compare a member of A is probably that you are not making it public or protected. By default, members of a class are private, and a private member cannot be seen by a derived class.
You need:
class A{ // declaration is simplified
{
virtual void FNC1();
protected:
bool compare( S s1, S s2 ){...}
};
Say I have a class with some const reference member variable and I would like to forbid a certain type of construction. So I would declare the according constructor private. Of course, a constructor must initialise all const reference member variables of the class. Doing so, however, results in odd looking code:
class A {
};
class B {
B(const A& a): host(a) {}
private:
B():host(A()) {} // This is ugly and not needed !!
const A& host;
};
Is there another way to prohibit a certain construction type except than declaring the constructor private? I do not want to let the compiler write a constructor for me.
Simply don't define this:
B():host(A()) {} // This is ugly and not needed !!
That is, the following should do what you want to do:
class B {
B(const A& a): host(a) {}
private:
//B():host(A()) {} // This is ugly and not needed !!
const A& host;
};
The idea is if you've defined a constructor that takes parameter(s), then the default constructor is not generated by the compiler. That means, instances of the above class cannot be default created!
B b1; //error - needs default constructor which doesn't exist!
B b2(a); //ok - only way to create an instance!
C++11 solution
In C++11, you can explicity tell the compiler not to generate a particular constructor as:
struct B
{
B(const A &a) {}
B() = delete; //disable
};
Not only that. There is more to it, as explained below:
Now the interesting part
You can also selectively disable constructor(s) for selected types which makes delete more interesting. Consider this,
struct A
{
A (int) {}
};
Object of this class can be created not only with int argument, but any type which implicitly converts to int. For example,
A a1(10); //ok
A a2('x'); //ok - char can convert to int implicitly
B b;
A a3(b); //ok - assume b provides user-defined conversion to int
Now suppose, for whatever reason, I don't want the users of class A to create objects with char or class B , which fortunately or unfortunately can implicitly convert to int, then you can disable them as:
struct A
{
A(int) {}
A(char) = delete; //disable
A(const B&) = delete; //disable
};
Now here you go:
A a1(10); //ok
A a2('x'); //error
B b;
A a3(b); //error - assume (even if) b provides user-defined conversion to int
Online Demo : http://ideone.com/EQl5R
The error messages are very clear:
prog.cpp:9:5: error: deleted function 'A::A(char)'
prog.cpp:10:5: error: deleted function 'A::A(const B&)'
Just leave it out. As soon as you provide a custom constructor, no other constructor is auto-generated (except for a copy constructor).
If you want to forbid any construction – ending up with a class that has only static members – you can simply declare the constructor as private, and not define it. Such a class is very rarely useful in C++ (since you cannot create instances of it); the only purpose that I can think of is to implement trait classes:
template <typename T>
struct type_to_color {
static char const* value() { return "blue"; }
private:
type_to_color();
};
template <>
struct type_to_color<int> {
// Integers are red!
static char const* value() { return "red"; }
private:
type_to_color();
}
char const* char_color = type_to_color<char>::value();
char const* int_color = type_to_color<int>::value();
However, this is extremely uncommon: trait classes are abundant in C++ but they never declare their constructors as private, it’s just assumed that everybody knows not to instantiate them.
I'll post the C++11 solution: delete the constructor.
class B {
B() = delete;
B(const A& a): host(a) {}
private:
const A& host;
};
As Konrad Rudolph sayd: as soon you provide a custom constructor, no other constructor is auto-generated (except for a copy constructor).
Therefore, other options are:
Declare the constructor private (so that you can't inherit from your class), but do not provide a definition:
class B {
public:
B(const A& a): host(a) {}
private:
B(); // not implemented!
const A& host;
};
Or in C++11, as R. Martinho Fernandes says:
class B {
public:
B() = delete;
B(const A& a): host(a) {}
private:
const A& host;
};
what i have is two classes
//class A is a kind of config-class which have configuration details
//for class B
class A{
//....
};
class B{
public:
B(A const& _a)
:a(_a){}
private:
A const& a;
};
till this point everything is fine.
now i want is a B::configure(A const& _a) function so that i can dynamically pass the reference of configuration class A to class B which shall be assigned to the member variable a. but i'm not able to change the member variable B::a as it is a const&.
what can be the work around?
i think #Seth Carnegie's approach is better, i should use a pointer to class A inside class B in this way:
class B{
public:
B(A const& _a)
:a(_a){}
configure(A const& _a)
{ a = &_a; }
private:
A const* a;
};
You cannot alter a reference after it's been initialized, whether it is const or not. The const just keeps you from making alterations to the variable that the reference refers to. So to change the variable after the instance has been constructed, you'll have to use pointers rather than references.
Your grammar was rather unclear, tell me if I misunderstood the question.