I have a library given to me where I am supposed to subclass one of its struct for use in my own app. When I do this, it works fine. However, when I change my subclass definition to class instead of struct (and I make sure to public: before everything inside), the compiler (Visual Studio compiler 10) gives me this odd error:
typecast: conversion exists but is inaccessible
The line on which this error occurs looks like this:
LibraryNameSpace::Client c(config_options, &mySublassObject);
I don't understand why a simple change from struct to class creates this error; any compiler-added default constructors would apply to either struct or class, including conversion constructors (if that's the issue here).
Is it perhaps because creating a class subclass from a struct base class is not a good idea?
Members of a 'struct' are public by default, whereas members of a 'class' are private by default. If you do not specify public/private, all members in the 'struct' become private when you change it to 'class'.
Also did you inherit by private or public?
class Subclass : public SuperClass {
public:
// ...
};
Related
What am I doing wrong here? I cannot believe the below doesn't compile. Do you need to use a shared pointer cast or something?
struct Base
{
};
class Child : Base
{
};
int main()
{
std::shared_ptr<Base> p = std::make_shared<Child>();
}
The error I get with Microsoft compiler is
error C2440: 'initializing': cannot convert from 'std::shared_ptr<Child>' to 'std::shared_ptr<Base>'
It does work. It's just that Base has private inheritance.
struct Child : Base{};
or
class Child : public Base{};
are fixes. Interestingly std::static_pointer_cast and company do exist; but you don't need them here. See https://en.cppreference.com/w/cpp/memory/shared_ptr/pointer_cast
Although #Bathsheba's and #divinas's answers solved this issue, none of them explained why is this the solution, and I think it's important for future viewers to know why is it the problem in this case.
When you are trying to create a pointer to the base class Base you are trying to get an access to all of the public members of the base that belong to the derived class (in this case Child). If the derived class privately inherit the base class (or protected inherit it), all of the members that labeled as public in the base class, inside the derived class now labeled as private (or protected). Which means that the attempt to access them as public members will raise an access privileges violation issue. Because the access privileges is known at the compile time, this is a compilation error.
The solve, as mentioned in previous responses, is to inherit the base class using public inheritance. Which is the default inheritance in structs and non-default inheritance in classes.
You should use public inheritance instead:
class Child : public Base
{
};
This is likely a basic question, but I haven't seen this done before and I haven't found a reference that talks about it:
What is going on in the following code:
using HandlerType = std::function<bool()>;
class SpecificAction : public Action<HandlerType>
{
public:
using Action::Action;
};
Specifically, what is the reason for the 'using Action::Action'? Action is a class template with a bunch of methods defined for it, but this is the entire declaration for SpecificAction.
When you are defining a class SpecificAction deriving from Action, everything in Action is added to SpecificAction, except the constructors. This syntax is a way to tell the compiler that you want to use the constructor from Action as a constructor for SpecificAction.
The reason constructor are not added by default to the derived class is that the derived class is likely to add some more data members which will not be initialized by the base constructor. Using this syntax you're telling the compiler that it's ok, you know what you're doing.
Unfortunately, I studied class design and design patterns mostly in the context of Java; thus, I sometimes have a hard time to translate a familiar pattern to C++.
Assume we want to have a base class which's functionality is extended by a sub-class. In Java, we would do something like this:
public class BaseClass<T> {
//T is used here
protected int foo = 0;
}
public class DerivedClass<T> extends BaseClass<T> {
public void incr_foo() {
++foo;
}
}
Which I directly translated to C++:
template<class T>
class BaseClass {
protected:
size_t foo = 0;
//T is used here
};
template<class T>
class DerivedClass : public BaseClass<T> {
public:
void incr_foo() {
++(this->foo);
}
};
Since the C++ semantics of 'protected' diver from the Java-semantics, we need to use something like 'this->foo' to access protected members of the base class.
Edit: If we just use '++foo', the compiler gives the error: 'use of undeclared identifier foo'.
EditEnd
If you need to access several members of the base class, this can get a bit tedious and is not so nice to read.
Is this a good design desicion? If not, what better ways are there to achieve this?
This has nothing to do with the member being protected; you'd get the exact same error with a public member.
The real reason is that templates are involed. More specifically, that your class template has a base class which depends on a template parameter. This means that when parsing the template, the compiler will not (be able to) look into that base class to find inherited members which are used unqualified. It makes sense: when the template is parsed, the template parameter values are not known yet and thus the compiler has no idea what members the base class will have (remember partial and total specialisation exist!).
In order to overcome this, you must somehow tell the compiler that the name foo depends on template parameters (that it's a dependent name). Once you do so, the compiler will not try to resolve it when parsing the template; it will postpone resolution until the template is instantiated. At that point, template arguments are known and thus the base class can be checked.
You have three ways to mark a member name as dependent:
Refer to the name through this, as you're doing: this->foo
Refer to the name through base-class qualification: BaseClass<T>::foo
Bring the name into the scope of the derived class:
template<class T>
class DerivedClass : public BaseClass<T> {
protected:
using BaseClass<T>::foo; // from this point on, `foo` is a dependent name
public:
void incr_foo() {
++foo; // works fine now
}
};
BaseClass<T> is a dependent type - it depends on the template parameter used to instantiate DerivedClass. Until DerivedClass instantiated, the compiler doesn't know what the type is: it might be an instantiation of the generic template, or it might be an explicit specialisation, with different members.
So, within the definition of DerivedClass, there is no way to know which names refer to members of the base class. You have to specify that they are, using this-> or BaseClass::.
In a class with a non-dependent base class, you can use any accessible base-class members as if they were direct members, just as in Java.
So in the header file of my derived class OrderedList I am inheriting some of the functionality of my previously created List class by telling the compiler to use a base class method by using List<DataType>::examplefunction;. All the functions which are not being overrided and that are being declared in the aforementioned way are private members of OrderedList.
So when I run my program, I obtain the error in Microsoft Visual Studio of:
error C2248: 'OrderedList::examplefunction' : cannot access private member declared in class 'OrderedList'
examplefunction is public in the base class List.
Here is a concrete example of what I am working with:
In OrderedList.h,
private:
using List<DataType>::remove;
In List.h,
public:
void remove () throw ( logic_error );
And where remove is in List.cpp as,
void List<DataType>::remove () throw ( logic_error )
{ // Do some operations//
}
Also the declaration in my OrderedList header file is like this:
#include "List.cpp"
template < typename DataType, typename KeyType >
class OrderedList : public List<DataType>
If anyone could enlighten me to what is causing the issue that would be much appreciated.
If exampleFunction is private in your List class, your OrderedList class will not be able to access it. Make it protected instead. See Private and Protected Members : C++
Moving the inherited methods to public and the data members to protected in the OrderedList header file worked.
Update
So this was about a year ago. However, it seems so blatantly obvious now. The instructions that were given said to declare the inherited methods from the base class (List) as private, but in main which was provided by the author of the textbook (for testing purposes) some of the inherited methods were being called. Which while being private were not able to be called by the instance of OrderedList that was being created in main.
The instructions were later corrected by our instructor, but sometimes as a student you can follow along to closely.
I have not used C++ for a really (really) long time and this question may be stupid but I could really use some help.
If my base class has a private data member and my derived class is derived publicly, the private members of the base class are NOT inherited. But, they can still be accessed via the inherited public functions. Eg:
class B{
int a,b;
public:
void SetA(int);
int GetA();
};
class D:public B{
public:
SetAAttribute(int x)
{ SetA(x); }
}
Now, my question is as follows:
Technically, the derived class objects do not have the 'a' attribute defined on them. In layman terms, I am basically setting an attribute on an entity when the attributes does not even exist in the first place. It seems unintuitive to imagine such a concept. Did I understand this correctly?
Any extra explanation or correction would be greatly appreciated.
It's not that the attribute doesn't exist anymore, it's just that it's hidden from you. The base class methods can still access the base class members because they're not hidden from each other.
The private base members are inherited, the compiler will just give you an error if you try to access them, since you aren't supposed to access them directly.