How to access function of a class in switch case - visual-c++

I am trying to access function of a class in switch case but identifier not found error is coming.Here is the example.
class menu {
switch(a) {
case 1:
tej t;
t.do_something
break;
}
};
class tej:public menu {
public:
void do_something() {
body of function
}
};

There are a few things missing from your code:
Have you forgotten the parentheses after do_something?
Also, are you missing a function somewhere? You can't put a switch statement directly in the class.
You can't declare variables directly in the switch statement. You need an extra set of braces for that.
class menu {
public:
void do_switch(int a) { // Note function
switch(a) {
case 1:
{ // You need an extra set of braces if you intend to declare variables
tej t;
t.do_something(); // <-- N.B. Parentheses!
}
break;
}
} // Note extra brace to close function
};
class tej:public menu {
public:
void do_something() {
// body of function
}
};
I highly recommend that you pick up a good introductory C++ book, as the things you're getting wrong are quite fundamental to the language. It's less frustrating that way.

Related

Enum resolution conflicting with class names

In one package / module I have the following code
// Pieces.hx
package;
#:structInit class Piece {
public var type: PieceType;
public var value: Int;
public function new(
type: PieceType,
value: Int,
) {
// do some stuff
}
}
var Pawn:Piece = { type: PieceType.Pawn, value: 1 }
enum PieceType {
Pawn;
}
Then in another file i have code trying to use the value property
// Game.hx
import Pieces.Pawn
import Pieces.PieceType;
class Main {
override function init() {
var value = Pawn.value
}
}
The error I'm getting when I try to compile is
src/Main.hx:46: characters 29-33 : PieceType has no field tile
What would be the correct way to structure this so that the Pawn that is imported is the class not the PieceType enum?
Another question is do I even need the enum at all? If I wanted write a switch statement can I just check if the passed argument is a Pawn class?
ex
function switch(p: Piece) {
switch(P) {
case Pawn: // Is true?
}
}
The convention for Haxe is that variable names are camelCase, which means that they begin with a lowercase character. In this case, this would solve your problem as the variable name would be pawn and the enum name would be Pawn so they would not conflict.
Alternatively, assuming the value field is the same for every pawn and doesn't change, you could have a map to retrieve this instead of adding it to an instance:
// Pieces.hx
enum PieceType {
Pawn;
Rook;
...
}
private final valueByPieceType:Map<PieceType, Int> = [
Pawn => 1,
Rook => ...,
...
];
function getValue(pieceType:PieceType):Int {
return valueByPieceType[pieceType];
}
// Game.hx
import Pieces.PieceType;
import Pieces.getValue;
class Main {
override function init() {
var value = getValue(Pawn);
}
}
This avoids requiring the extra instance/class in this example. If all pawns are meant to have this value then this is better as it ties the value to the fact it is a Pawn and prevents you from accidentally creating a pawn with a value other than 1.
However, if for whatever reason neither of those options are helpful, perhaps I would suggest changing the enum value to something like TPawn. Otherwise, only if absolutely necessary, you could create an alias within the Game.hx, however, this is not a good solution as then the Pieces module is unusable without adding this extra bit everywhere.
// Game.hx
import Pieces.Pawn as PawnPiece;
import Pieces.PieceType;
class Main {
override function init() {
var value = PawnPiece.value;
}
}
Keeping the enum and switch statement is also useful, as it prevents you from making mistakes because the compiler will ensure that you check every possibility, so you don't miss out any pieces. The switch is also more concise than having a manual check for every single piece type.

Issue calling a method of class using this when function is called using super

class Dog {
bark () {
console.log(`Dog.bark`)
}
callMyBark () {
// how do I have this function use the bark above and not Pug.bark?
this.bark()
}
}
class Pug extends Dog {
bark () {
console.log(`Pug.bark`)
}
callMyBark () {
super.callMyBark()
}
}
let pug = new Pug()
pug.callMyBark()
The above code logs Pug.bark and the expected behavior is to log Dog.bark. How can I have the Dog.callMyBark method run Dog.bark instead?
There are a few ways to do this, but I think the best is to call the super method or just not override at all:
class Pug extends Dog {
bark () {
super.bark(); // or omit the method entirely
}
callMyBark () {
super.callMyBark()
}
}
Obviously that doesn't take into account where you're calling from, which seems to be how you want to decide.
Bear in mind that choosing the method based on caller like that is something of an antipattern in most OO languages and much work has been done to avoid accidentally doing that (it was a problem in C++, which is part of why later languages default to virtual dispatch).
I would strongly suggest making the function static or some detached helper if you really need to and calling it directly:
class Dog {
static bark() {
console.log(`Dog.bark`)
}
callMyBark () {
// how do I have this function use the bark above and not Pug.bark?
Dog.bark()
}
}
If you need this within the function, you can pass an instance to the helper, or you can call through the prototype (or the instance's prototype chain):
class Dog {
bark() {
console.log(`Dog.bark`)
}
callMyBark () {
// how do I have this function use the bark above and not Pug.bark?
Dog.prototype.bark.call(this);
}
}
There is no pretty solution, likely because this can typically be avoided.

Using abstracts as HashMap keys in Haxe

I'm trying to create a haxe.ds.HashMap where the keys are an object I don't control. Thus, they don't implement the hashCode method and I can't change them to.
I would really like to use an abstract to accomplish this, but I'm getting some compile time errors.
Here is the code I'm playing with:
import haxe.ds.HashMap;
abstract IntArrayKey( Array<Int> ) from Array<Int> {
inline public function new( i: Array<Int> ) {
this = i;
}
public function hashCode(): Int {
// General warning: Don't copy the following line. Seriously don't.
return this.length;
}
}
class Test {
static function main() {
var hash = new HashMap<IntArrayKey, Bool>();
}
}
The compile errors are:
Test.hx:15: characters 19-51 : Constraint check failure for haxe.ds.HashMap.K
Test.hx:15: characters 19-51 : IntArrayKey should be { hashCode : Void -> Int }
But the moment I change my abstract over to a class, it compiles fine:
import haxe.ds.HashMap;
class IntArrayKey {
private var _i: Array<Int>;
inline public function new( i: Array<Int> ) {
this._i = i;
}
public function hashCode(): Int {
// General warning: Don't copy the following line. Seriously don't.
return this._i.length;
}
}
class Test {
static function main() {
var hash = new HashMap<IntArrayKey, Bool>();
}
}
It's the exact same hashCode implementation, just a different context. Is there some way to accomplish this? Or is it a language limitation?
As far as I know, abstracts currently can't satisfy type requirements like this, quoting from the code:
abstract HashMap<K:{ function hashCode():Int; }, V >(HashMapData<K,V>) {
So, I doubt you could do that in a meaningful way.
Important point would be that while abstracts can sometimes provide overhead-free abstractions which is quite useful for optimizations, the time needed to instantiate(probably hidden from sight with abstract Name(Holder) to Holder having #:from Array<Int> and #:to Array<Int>) holder for your array which will have the required method isn't that high(compared to usual runtime overheads), and unless it is a really frequent code, should be your first way to go.
However, the HashMap code itself is quite short and simple: here.
You could just copy it and make it work with your example. Maybe you could even forge a better yet generic version by using interfaces(though I'm not sure if abstracts can actually implement them).

Pattern / architecture / anonymous methods

I am relatively new to C#, maybe you could help me with this.
I got a couple of methods callServiceXY(param1, param2, ...) that call a certain service. For many reasons these service calls can go wrong (and I don't really care for the reason in the end). So basically I need to always wrap them with something like this - to have them execute again if something goes wrong:
var i = 3;
while(i>0)
try{
call...()
} catch{
i--;
}
i=0;
}
I'd rather write this code only once. Could I somehow have a method like tryXtimes(int x, callService()) that allows me to execute an undefined or anonymous method? (I have Javascript in mind where this is possible...)?
Yes this is possible. C# 3.5 added support for Action and Func<T> types. An Action won't return any value, a Func will always return a value.
You have several different versions that also accept a number of parameters. The following Console Applications describes how you could do this:
using System;
namespace Stackoverflow
{
class Service
{
public int MyMethod() { return 42; }
public void MyMethod(string param1, bool param2) { }
public int MyMethod(object paramY) { return 42; }
}
class Program
{
static void ExecuteWithRetry(Action action)
{
try
{
action();
}
catch
{
action();
}
}
static T ExecuteWithRetry<T>(Func<T> function)
{
try
{
return function();
}
catch
{
return function();
}
}
static void Main(string[] args)
{
Service s = new Service();
ExecuteWithRetry(() => s.MyMethod("a", true));
int a = ExecuteWithRetry(() => s.MyMethod(1));
int b = ExecuteWithRetry(() => s.MyMethod(true));
}
}
}
As you can see, there are two overloads for ExecuteWithRetry. One returning void, one returning a type. You can call ExecuteWithRetry by passing an Action or a Func.
--> Edit: Awesome! Just a little extra code to complete the example:
With anonymous function/method:
ExecuteWithRetry(() =>
{
logger.Debug("test");
});
And with more parameters (action, int)
Method header:
public static void ExecuteWithRetryX(Action a, int x)
Method call:
ExecuteWithRetryX(() => { logger.Debug("test"); }, 2);
I would use the strategy/factory pattern(s) for this. This answer https://stackoverflow.com/a/13641801/626442 gives and example of the use of the strategy/factory pattern with links. The question at the above link will give you another type of example where this pattern can be adopted.
There are great examples of these design patterns here and the following are detailed intros to the Strategy pattern and the Factory pattern. The former of the last two links also shows you how to combine the two to do something like what you require.
I hope this helps.
Try following
void CallServiceXY(params object []objects)
{
Console.WriteLine("a");
throw new Exception("");
}
void Retry(int maxRetryCount, Action<object[]> action, params object[] obj)
{
int retryCount = 1;
while ( retryCount <= maxRetryCount)
{
try
{
action(obj);
return;
}
catch
{
retryCount++;
}
}
}
void Main()
{
Retry(2,CallServiceXY);
Retry(2,CallServiceXY,"");
Retry(2,CallServiceXY,"","");
}
Demo here
Trick is Action<object[]> that accepts object array and return void and params keyword in Retry method.
To return non void value, Change Action<object[]> to Func<T, object[]>.

Passing parammeters

Hi guys I have one question,
If I have a sequence of methods for example:
Main()
{
Method1();
}
Method1()
{
Method2();
}
Method2()
{
Method3();
}
Method3()
{
ObtainsUserPermission(httpContext.Current.User.Name);
}
How is the best way to do it, using the parammeter "httpContext.Current.User.Name" in the last Method3, or passing by parammeter in each method? Like this:
Main()
{
Method1(httpContext.Current.User.Name);
}
Method1(string name)
{
Method2(name);
}
Method2(string name)
{
Method3(name);
}
Method3(string name)
{
ObtainsUserPermission(name);
}
thank you for all.
This smells like magic parameters.
A good rule of thumb is - if you wish your execution of method3() to depend on the name, pass the name as a parameter. In general, you shouldn't use globals inside functions. It can become complicated to debug and maintain. An exception is members of a class, in which case your members are visible inside the methods and there is no need to pass them as parameters.

Resources