Template Parameter Inheritance in C++ - c++

I haven't written C++ in a while, so I'm a bit rusty. If I have a class like this:
class JsonType{
protected:
map<string, JsonType>* objects;
}
and a class that inherits from that:
class JsonObject : public JsonType{
public:
JsonObject(){
this->objects = new map<string, JsonObject>();
}
}
why would I be getting a compiler error cannot convert...JsonObject...to...JsonType? Shouldn't that be legal, since JsonObject is a JsonType?

You can add JsonObject objects to the map, but the types do not match for initialization.
Edit: You have to initialize it as:
this->objects = new map<string, JsonType>();
But if you have either objects:
JsonType js = new JsonType();
or
JsonObject js2 = new JsonObject();
or
JsonType js3 = new JsonObject();
You can add any of these objects to the map initialized as above.

objects doesn't use JsonObject for its value_type, it uses JsonTypes.
In other words you are allocating the wrong kind of map to store into objects.

Related

Dot notation for list of object in class

I have a "fixed list" in a class, I know all the objects that are in that list and I can refer to the objects through the names. The list is immutable, except for the parameters of every object contained in this list.
Something like this
class Object {
String name; // Know prior to build time
String color; // Can change
Object(this.name, this.color);
}
class MyClass {
List<Object> myList = [Object('apple', 'red'),
Object('banana', 'yellow'),
Object('mango', 'orange')];
}
I would like to access the members of the list like
final test = MyClass();
test.myList.apple.color = 'green'
Is there some "special list" that consent this type of access?
I tried using ENUM but they are not suitable for this problem.
A Map<String, String> would be better suited for what you are trying to do.
final colors = HashMap<String, String>();
colors['apple'] = 'green';

Better way to write common function with parameter is different class

In my project, I have some functions like that:
func 1 (with 2 class: class1 and classs1_1):
List<class1> GetData1(class1_1 cls)
{
List<class1> list = new List<class1>();
cls = new cls();
//do something for cls, like cls.GetSpecialCase();
//fill data from cls to list, as using foreach to fill data to list
return list;
}
func 2 (with 2 class: class2 and classs2_2):
List<class2> GetData2(class2_2 cls)
{
List<class2> list = new List<class2>();
cls = new cls();
//do something for cls, like cls.GetSpecialCase();
//fill data from cls to list, as using foreach to fill data to list
return list;
}
How could I write a function like that (because I don't want to use a lot of functions as above):
common func (with T is class1, object cls is class1_1):
List<T> GetData(object cls)
{
List<T> list = new List<T>();
//how to recognize which class of cls
if(cls == class1_1) class1_1 other_cls = cls as class1_1;
if(cls == class2_2) class2_2 other_cls = cls as class2_2;
//do something for other_cls
//fill data from other_cls to list
return list;
}
I just want to pass parameter as object, and in the common function, I want to know which class I'm passing to so that I can treat to right class, and call right function.
Anyone helps me to solve this problem.
Thank you very much.
It sounds like you need:
An interface or abstract base class with the GetSpecialCase method
A generic method (with type parameters for both input and output) of
List<TResult> GetData<T, TResult>(T item) where T : ISpecialCase<TResult>
{
List<TResult> list = new List<TResult>();
var other = item.GetSpecialCase();
// Fill list via other
return list;
}
If you can't introduce an interface or base class, you could use dynamic typing, but I'd strongly recommend that you use polymorphism to express what the different classes have in common (GetSpecialCase here) if you possibly can.
you can use generics also for the input type.
your code could be something like:
List<T> GetData<T>(T cls)
{
List<T> list = new List<T>();
//no need to recognize which class of cls
//do something for other_cls
//fill data from other_cls to list
return list;
}
and both classes needs to implement the same interface so you wouldn't need to know which type it is...

How to override KeyValuePair<TKey, TValue> in C#?

I want to override the default structure of KeyValuePair in C#, so that I can make a KeyValuePair to accept a 'var' types.
Something like this :
List<KeyValuePair<string, var>> kvpList = new List<KeyValuePair<string, var>>()
{
new KeyValuePair<string, var>("Key1", 000),
new KeyValuePair<string, var>("Key2", "value2"),
new KeyValuePair<string, var>("Key3", 25.45),
};
Even if its possible for dictionary, then also it will solve my problem.
You could use object as your type, and then cast to/from object to desired outcomes. However, it's important to note that this is very much the opposite of object oriented programming, and generally indicates an error in your design and architecture.
Hmm I am wondering if this might help you: To have a list as you want, it is really possible BUT the "var" type (as you named it) must be the same for all KeyValuePair instances. For having whatever type you must use object or dynamic (use Haney's answer).
So considering that you want a single type for all KeyValuePair instances, here is a solution:
Firstly, create this helper class:
public static class KeyValuePairExtentions
{
public static List<KeyValuePair<string, T>> GetNewListOfType<T>(Expression<Func<T>> type)
{
return new List<KeyValuePair<string, T>>();
}
public static void AddNewKeyValuePair<T>(this List<KeyValuePair<string, T>> #this, string key, T element)
{
#this.Add(new KeyValuePair<string, T>(key, element));
}
}
To consume these functions, here is an example:
var lst = KeyValuePairExtentions.GetNewListOfType(() => new {Id = default (int), Name = default (string)});
lst.AddNewKeyValuePair("test1", new {Id = 3, Name = "Keith"});
The ideea is to rely on the powerfull type inference feature that we have in C#.
Some notes:
1) if T is anonymous and you create a new instance of a list in an assembly and consume it in another assembly it is VERY possible that this will NOT work due to the fact that an anonymous type is compiled per assembly (in other words, if you have a variable var x = new { X = 3 } in an assembly and in another var y = new { X = 3 } then x.GetType () != y.GeTType () but in the same assembly types are the same.)
2) If you are wondering whether an instance it's created or not by calling GetNewListOfType, the answer is NO because it is an expression tree function and the function is not even compiled. Even with a Func will work because I am not calling the function in my code. I am using the function just for type inference.

How to add items to a list of type List<? extends Object>

I have a list which is of type -
List<? extends Object> = new ArrayList<oracle.jbo.domain.Date> ();
But when I try to add the items to this list I get compile time error -
this step -
a.add( new oracle.jbo.domain.Date() );
will throw following error -
Error(183,22): cannot find method add(oracle.jbo.domain.Date)
How to add elements to this list ?
Any help is appreciated.
Thanks
If your ArrayList contains oracle.jbo.domain.Date instances, why are you saving the reference to a List<? extends Object>? Using generics in reference should be avoided (as you can check here) when you want to insert elements in the list. But your ArrayList can only contain one kind of data so:
List<oracle.jbo.domain.Date> a = new ArrayList<oracle.jbo.domain.Date>();
a.add( new oracle.jbo.domain.Date() );
But if you really have a List<? extends Object>, then sorry but you can't insert elements to that list. In fact the compiler has no int about which kind of list it is. This is different from:
List<Object> a = new ArrayList<Object>();
In fact in that case you know you can add anything, because everything extends Object. But in this case any of those are legal assignments:
List<? extends Object> a = new ArrayList<Integer>();
List<? extends Object> a = new ArrayList<Double>();
List<? extends Object> a = new ArrayList<String>();
and the compiler doesn't know which one is the current case. So you are prevented from inserting elements. This is commonly used to make read-only objects.

Error to instantiate one class in form c++

I need insert one object in the linked list when i clicked a button
but when i make instantiate the class List this shows me one error
public ref class Boletos : public System::Windows::Forms::Form
{
public:
Boletos(void)
{
Lista *List=new Lista;
InitializeComponent();
//
//TODO: Add the constructor code here
//
}
//*****************Click_event**********************//
...
if (count==4){
Capacidad=Convert::ToInt32(line);
capc=Capacidad;
//sala->set_capacidad(Capacidad);
Sala *sala=new Sala();
List->insertAlFinal(newSala(numSala,HPeli,capc,"",2000,nombrePelicula));//Here the error List undefined
count=0;
}
u are placing your code at the wrong position, its so to say out of scope. Btw. this is not really c++, looks like c# ...
Try something like
Boletos(void)
{
Lista* list = new Lista();
InitializeComponent();
}
What u need is a class member.
public ref class Boletos ...
{
public:
....
void InitializeComponent()
{
m_lista = new Lista();
}
private:
Lista* m_lista;
}
now u can use m_lista in all the classes member functions. What u need to understand is the concept of scope. If u declare and intialize a variable only in the scope of one function this variable is so to say lost after the program leaves the scope of this function. In the case of c++ the dynamich alloaction new Lista() without a matching call to delete would even be a memory leak.